2013-05-24 5 views
83

Tôi đã lớp sau đây được tạo ra bởi khuôn khổ tổ chức:Thêm chú thích dữ liệu vào một lớp được tạo ra bởi khuôn khổ thực thể

public partial class ItemRequest 
{ 
    public int RequestId { get; set; } 
    //... 

tôi muốn thực hiện điều này một trường bắt buộc

[Required] 
public int RequestId { get;set; } 

Tuy nhiên, bởi vì đây được tạo ra mã này sẽ bị xóa sổ. Tôi không thể tưởng tượng một cách để tạo ra một lớp một phần vì thuộc tính được định nghĩa bởi lớp từng phần được tạo ra. Làm thế nào tôi có thể xác định ràng buộc một cách an toàn?

+0

Nếu thuộc tính của bạn là int, theo mặc định, nó được yêu cầu cho modelbinder để thuộc tính [Bắt buộc] của bạn sẽ không thêm bất kỳ thứ gì ở đây. –

+0

@KirillBestemyanov - @ Html.ValidationMessageFor (model => model.Item.Item.ResourceTypeID) sẽ không thành công ở phía máy khách. Nó không. –

Trả lời

122

Lớp được tạo ItemRequest sẽ luôn là lớp partial. Điều này cho phép bạn viết một phần lớp thứ hai được đánh dấu bằng các chú thích dữ liệu cần thiết. Trong trường hợp của bạn partial class ItemRequest sẽ trông như thế này:

using System.ComponentModel; 
using System.ComponentModel.DataAnnotations; 

//make sure the namespace is equal to the other partial class ItemRequest 
namespace MvcApplication1.Models 
{ 
    [MetadataType(typeof(ItemRequestMetaData))] 
    public partial class ItemRequest 
    { 
    } 

    public class ItemRequestMetaData 
    { 
     [Required] 
     public int RequestId {get;set;} 

     //... 
    } 
} 
+2

Tôi giả sử rằng bạn vẫn cần thêm "chú thích [MetadataType (typeof (ItemRequestMetaData))]" của bạn lên đầu lớp ItemRequest mỗi khi nó được tạo lại? – Alicia

+10

Lớp học một phần sẽ không được phục hồi. Đó là lý do tại sao nó được định nghĩa là một phần. – MUG4N

+3

Tôi nhận được bạn ngay bây giờ, bạn tạo một phần gốc cho cùng tên với lớp được tạo lại, ví dụ: ItemRequest trong trường hợp này và đặt chú thích xung quanh, điều này rất hữu ích, cảm ơn bạn! – Alicia

2

Tôi không chắc chắn làm thế nào để làm những gì bạn đang yêu cầu nhưng có một cách xung quanh nó. Xác thực dữ liệu động bằng cách ghi đè GetValidators của DataAnnotationsModelValidatorProvider tùy chỉnh của bạn. Trong đó, bạn có thể đọc các quy tắc để xác nhận từng trường (từ cơ sở dữ liệu, tệp cấu hình, v.v.) và thêm trình xác nhận là cần thiết. Nó có các giá trị gia tăng mà việc xác thực của bạn không còn được kết hợp chặt chẽ với mô hình và có thể thay đổi mà không cần phải khởi động lại trang web nữa. Tất nhiên nó có thể là quá mức cần thiết cho trường hợp của bạn, nhưng nó là lý tưởng cho chúng ta!

+0

Bạn có khung Entity với DbContext không? – Max

+0

Chúng tôi đã làm khi lần đầu tiên chúng tôi triển khai cấu trúc này. Chúng tôi đã chuyển sang NHibernate, nhưng điều này không mang về giải pháp. Mã xác thực của chúng tôi hoạt động như không có thay đổi (chỉ có lớp truy cập dữ liệu đã được thay đổi). – JTMon

36

Như MUG4N trả lời bạn có thể sử dụng các lớp học phần nhưng sẽ sử dụng tốt hơn giao diện để thay thế. Trong trường hợp này, bạn sẽ có lỗi biên dịch nếu mô hình EF không tương ứng với mô hình xác nhận. Vì vậy, bạn có thể sửa đổi các mô hình EF của bạn mà không sợ rằng các quy tắc xác nhận đã lỗi thời.

using System.Collections.Generic; 
using System.ComponentModel.DataAnnotations; 

namespace YourApplication.Models 
{ 
    public interface IEntityMetadata 
    { 
     [Required] 
     Int32 Id { get; set; } 
    } 

    [MetadataType(typeof(IEntityMetadata))] 
    public partial class Entity : IEntityMetadata 
    { 
     /* Id property has already existed in the mapped class */ 
    } 
} 

P.S. Nếu bạn đang sử dụng loại dự án đó là khác với ASP.NET MVC (khi bạn thực hiện thủ công xác nhận dữ liệu) đừng quên đăng ký xác nhận của bạn

/* Global.asax or similar */ 

TypeDescriptor.AddProviderTransparent(
    new AssociatedMetadataTypeTypeDescriptionProvider(typeof(Entity), typeof(IEntityMetadata)), typeof(Entity)); 
+0

Hoạt động như sự quyến rũ! Cảm ơn, @dimonser. –

+0

@dimonser giải pháp tốt đẹp, tôi đã cố gắng thêm xml ý kiến ​​như thế này cũng (đối với những lĩnh vực DB cần một chút giải thích trong mã - tức là được hiển thị trong intellitype) nhưng nó không có vẻ làm việc. Có ý tưởng nào để làm việc này không? – Rick

+0

Xin chào @Rick, bạn có thể đặt nhận xét về thuộc tính giao diện, nhưng bạn sẽ chỉ thấy nhận xét khi bạn làm việc với biến giao diện. Hoặc bạn có thể đặt một bình luận trong một lớp học. Trong trường hợp này, bạn sẽ thấy nó khi bạn làm việc với một thể hiện của lớp của bạn. Không có trường hợp nào khác. Trong trường hợp đầu tiên bạn có thể mô tả các quy tắc xác nhận trường và trong trường hợp thứ hai, hãy cố gắng mô tả mục đích – dimonser

4

Đây là loại phần mở rộng cho @dimonser câu trả lời nếu bạn tái sinh của bạn Mô hình db, bạn sẽ phải tự thêm lại các giao diện trên các lớp đó.

Nếu bạn có dạ dày cho nó, bạn cũng có thể sửa đổi .tt bạn mẫu:

Dưới đây là ví dụ về các giao diện tự động tạo ra trên một số lớp học, đây là đoạn từ .tt chỉ cần thay thế EntityClassOpening phương pháp trong bạn với sau (và rõ ràng var stringsToMatch với tên và giao diện thực thể của bạn).

public string EntityClassOpening(EntityType entity) 
{ 
    var stringsToMatch = new Dictionary<string,string> { { "Answer", "IJourneyAnswer" }, { "Fee", "ILegalFee" } }; 
    return string.Format(
     CultureInfo.InvariantCulture, 
     "{0} {1}partial class {2}{3}{4}", 
     Accessibility.ForType(entity), 
     _code.SpaceAfter(_code.AbstractOption(entity)), 
     _code.Escape(entity), 
     _code.StringBefore(" : ", _typeMapper.GetTypeName(entity.BaseType)), 
     stringsToMatch.Any(o => _code.Escape(entity).Contains(o.Key)) ? " : " + stringsToMatch.Single(o => _code.Escape(entity).Contains(o.Key)).Value : string.Empty); 
} 

Không có người bình thường nên làm điều này với chính mình, mặc dù Kinh Thánh đã được chứng minh là người ta đến Địa ngục để làm điều này.

+3

đã bỏ phiếu cho trích dẫn kinh thánh chính xác như vậy – Mike

0

Sửa đổi mẫu T4 thêm chú thích cần thiết, tập tin này thường được đặt tên MODELNAME.tt

tìm nơi T4 đang tạo ra các lớp và phương pháp để biết được nơi để đặt các.

 <#=codeStringGenerator.IgnoreJson(navigationProperty)#> 


//create this method in file 
public string IgnoreJson(NavigationProperty navigationProperty){ 
      string result = navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? "" : @"[JsonIgnore] 
    [IgnoreDataMember]"; 

      return result; 
     } 

Bạn cũng sẽ cần phải thêm các không gian tên;

<#=codeStringGenerator.UsingDirectives(inHeader: false)#> 
using System.ComponentModel.DataAnnotations; 
using Newtonsoft.Json; 
using System.Runtime.Serialization; 

Tạo lại lớp học bằng cách lưu mô hình của bạn, tất cả các phương pháp của bạn nên được chú thích.

8

Tôi tìm thấy một giải pháp như câu trả lời MUG4N 's, nhưng thay vào đó, làm tổ lớp MetaData trong lớp thực thể, do đó làm giảm số lượng các lớp học trong danh sách namespace công cộng của bạn, và loại bỏ sự cần thiết phải có một tên duy nhất cho mỗi lớp siêu dữ liệu.

using System.ComponentModel.DataAnnotations; 

namespace MvcApplication1.Models 
{ 
    [MetadataType(typeof(MetaData))] 
    public partial class ItemRequest 
    { 
     public class MetaData 
     { 
      [Required] 
      public int RequestId; 

      //... 
     } 
    } 
} 
+0

Tôi thích điều này tốt hơn 'phương pháp tiếp cận chuẩn' bất kỳ sự thiếu hụt nào? – reidLinden

+0

Tôi đã sử dụng điều này trên tất cả các dự án của tôi. Dễ tổ chức hơn nhiều.Tôi cũng thêm các thuộc tính tùy chỉnh bằng cách sử dụng '[NotMapped]' bên trong lớp partial khi tôi cần chúng. –