C# 向实体框架生成的类添加数据注释
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16736494/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Add data annotations to a class generated by entity framework
提问by P.Brian.Mackey
I have the following class generated by entity framework:
我有以下由实体框架生成的类:
public partial class ItemRequest
{
public int RequestId { get; set; }
//...
I would like to make this a required field
我想让它成为必填字段
[Required]
public int RequestId { get;set; }
However, because this is generated code this will get wiped out. I can't imagine a way to create a partial class because the property is defined by the generated partial class. How can I define the constraint in a safe way?
但是,由于这是生成的代码,因此将被清除。我无法想象创建分部类的方法,因为该属性是由生成的分部类定义的。如何以安全的方式定义约束?
采纳答案by MUG4N
The generated class ItemRequestwill always be a partialclass. This allows you to write a second partial class which is marked with the necessary data annotations. In your case the partial class ItemRequestwould look like this:
生成的类ItemRequest将始终是一个partial类。这允许您编写标有必要数据注释的第二个分部类。在您的情况下,部分类ItemRequest将如下所示:
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;}
//...
}
}
回答by JTMon
I am not sure how to do what you are asking for but there is a way around it. Dynamic data validation by overriding the GetValidators of your custom DataAnnotationsModelValidatorProvider. In it you can read the rules for validating each field (from a database, config file, etc.) and add validators as need be. It has the added values that your validation is no longer tightly coupled to the model and can be changed without need to even restart the site. Of course it might be overkill for your case, but it was ideal for ours!
我不确定如何做你所要求的,但有一种解决方法。通过覆盖自定义 DataAnnotationsModelValidatorProvider 的 GetValidators 进行动态数据验证。您可以在其中阅读验证每个字段的规则(来自数据库、配置文件等)并根据需要添加验证器。它具有附加值,即您的验证不再与模型紧密耦合,甚至无需重新启动站点即可更改。当然,这对您的情况可能有点过分,但对我们来说却是理想之选!
回答by dimonser
As MUG4Nanswered you can use partial classesbut will be better use interfacesinstead. In this case you will have compilation errors if EF model doesn't correspond to validation model. So you can modify your EF models without fear that validation rules are outdated.
正如MUG4N回答的那样,您可以使用部分类,但最好使用接口。在这种情况下,如果 EF 模型与验证模型不对应,您将出现编译错误。因此,您可以修改 EF 模型而不必担心验证规则已过时。
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. If you are using project type which is differ from ASP.NET MVC (when you perform manual data validation) don't forget to register your validators
PS 如果您使用的是不同于 ASP.NET MVC 的项目类型(当您执行手动数据验证时),请不要忘记注册您的验证器
/* Global.asax or similar */
TypeDescriptor.AddProviderTransparent(
new AssociatedMetadataTypeTypeDescriptionProvider(typeof(Entity), typeof(IEntityMetadata)), typeof(Entity));
回答by Matas Vaitkevicius
This is sort of extension to @dimonser answer if you regenerate your db model you will have to manually re-add interfaces on those classes.
这是对@dimonser 答案的一种扩展,如果您重新生成数据库模型,您将不得不在这些类上手动重新添加接口。
If you have stomach for it you can also modify your .tttemplates:
如果你有胃口,你也可以修改你的.tt模板:
Here's example of auto-generating interfaces on some classes, this is fragment from .ttjust replace EntityClassOpeningmethod in yours with following (and obviously var stringsToMatchwith your entity names and interfaces).
这是在某些类上自动生成接口的示例,这是.tt将EntityClassOpening您的方法中的替换方法替换为以下内容的片段(显然var stringsToMatch还有您的实体名称和接口)。
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);
}
No normal person should do this to himself though, it has been proven in Bible that one goes to Hell for this.
正常人不应该这样对自己,圣经已经证明,人会为此下地狱。
回答by tswales
Modify the T4 template adding required annotations, this file is usually named MODELNAME.tt
修改T4模板添加需要的注解,这个文件通常命名为MODELNAME.tt
find where the T4 is creating the class and methods to know where to put these.
找到 T4 在哪里创建类和方法,以了解将这些放在哪里。
<#=codeStringGenerator.IgnoreJson(navigationProperty)#>
//create this method in file
public string IgnoreJson(NavigationProperty navigationProperty){
string result = navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? "" : @"[JsonIgnore]
[IgnoreDataMember]";
return result;
}
You will also need to add the namespaces;
您还需要添加命名空间;
<#=codeStringGenerator.UsingDirectives(inHeader: false)#>
using System.ComponentModel.DataAnnotations;
using Newtonsoft.Json;
using System.Runtime.Serialization;
Rebuild your classes by saving your model, all your methods should be annotated.
通过保存您的模型重建您的类,您的所有方法都应该被注释。
回答by Carter Medlin
I found a solution like MUG4N's answer, but instead, nesting the MetaDataclass within the entity class, thereby reducing the number of classes in your public namespace list, and eliminating the need to have a unique name for each metadata class.
我找到了像MUG4N的答案这样的解决方案,而是将MetaData类嵌套在实体类中,从而减少了公共命名空间列表中的类数量,并且无需为每个元数据类指定唯一的名称。
using System.ComponentModel.DataAnnotations;
namespace MvcApplication1.Models
{
[MetadataType(typeof(MetaData))]
public partial class ItemRequest
{
public class MetaData
{
[Required]
public int RequestId;
//...
}
}
}

