我有以下由实体框架生成的类:
public partial class ItemRequest
{
public int RequestId { get; set; }
//...
我想将此设为必填字段
[Required]
public int RequestId { get;set; }
但是,由于这是生成的代码,因此将被清除。我无法想象创建局部类的方法,因为该属性是由生成的局部类定义的。如何以安全的方式定义约束?
我有以下由实体框架生成的类:
public partial class ItemRequest
{
public int RequestId { get; set; }
//...
我想将此设为必填字段
[Required]
public int RequestId { get;set; }
但是,由于这是生成的代码,因此将被清除。我无法想象创建局部类的方法,因为该属性是由生成的局部类定义的。如何以安全的方式定义约束?
Answers:
生成的类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;}
//...
}
}
正如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 */
}
}
PS:如果您使用的项目类型不同于ASP.NET MVC(在执行手动数据验证时),请不要忘记注册验证器
/* Global.asax or similar */
TypeDescriptor.AddProviderTransparent(
new AssociatedMetadataTypeTypeDescriptionProvider(typeof(Entity), typeof(IEntityMetadata)), typeof(Entity));
我找到了类似于MUG4N答案的解决方案,但是,将MetaData
类嵌套在实体类中,从而减少了公共命名空间列表中类的数量,并消除了为每个元数据类使用唯一名称的麻烦。
using System.ComponentModel.DataAnnotations;
namespace MvcApplication1.Models
{
[MetadataType(typeof(MetaData))]
public partial class ItemRequest
{
public class MetaData
{
[Required]
public int RequestId;
//...
}
}
}
[NotMapped]
当我需要它们时,我也会在部分类中添加自定义属性。
这是@dimonser答案的一种扩展,如果您重新生成数据库模型,则必须手动在这些类上重新添加接口。
如果您有胃,也可以修改.tt
模板:
这是在某些类上自动生成接口的示例,这.tt
只是EntityClassOpening
您后面的replace 方法的片段(显然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);
}
但是,任何普通人都不应该对自己这样做,圣经已证明有人为此而去。
修改T4模板并添加所需的注释,此文件通常名为MODELNAME.tt
查找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;
}
您还需要添加名称空间。
<#=codeStringGenerator.UsingDirectives(inHeader: false)#>
using System.ComponentModel.DataAnnotations;
using Newtonsoft.Json;
using System.Runtime.Serialization;
通过保存模型来重建类,所有方法都应添加注释。