将数据注释添加到由实体框架生成的类

时间:2013-05-24 13:46:29

标签: c# entity-framework asp.net-mvc-4

我有实体框架生成的以下类:

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

我想将此作为必填字段

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

但是,因为这是生成的代码,这将被消灭。我无法想象一种创建分部类的方法,因为属性是由生成的分部类定义的。如何以安全的方式定义约束?

7 个答案:

答案 0 :(得分:138)

生成的班级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;}

        //...
    }
}

答案 1 :(得分:39)

由于 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。如果您使用的项目类型与ASP.NET MVC不同(当您执行手动数据验证时),请不要忘记注册您的验证器

/* Global.asax or similar */

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

答案 2 :(得分:13)

我找到了像 MUG4N 的答案这样的解决方案,而是将MetaData类嵌套在实体类中,从而减少了公共命名空间列表中的类数,并且不需要为每个元数据类创建唯一的名称。

using System.ComponentModel.DataAnnotations;

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

            //...
        }
    }
}

答案 3 :(得分:5)

如果重新生成数据库模型,这是@dimonser答案的一种扩展,您必须手动重新添加这些类的接口。

如果你有胃,你也可以修改你的.tt模板:

以下是在某些类上自动生成接口的示例,这是来自.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);
}

没有正常的人应该对自己这样做,但是在圣经中已经证明了一个人为此而去了地狱。

答案 4 :(得分:2)

我不确定如何做你要求的但是有办法解决它。通过覆盖自定义DataAnnotationsModelValidatorProvider的GetValidators进行动态数据验证。在其中,您可以阅读验证每个字段的规则(来自数据库,配置文件等),并根据需要添加验证器。它具有附加值,您的验证不再与模型紧密耦合,无需重新启动站点即可进行更改。当然,对你的情况来说可能有点过头了,但它对我们来说是理想的!

答案 5 :(得分:1)

修改添加所需注释的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;

通过保存模型重建您的课程,所有方法都应注释。

答案 6 :(得分:0)

这个与控制器一起工作的解决方案我的意思是 ModelState.Isvalid 在视图上验证我的验证但我无法在将表单发布到控制器之前将我的表单解析为 javascript jquery.validate.unobtrusive.min.js 以在客户端切换验证。正在使用 ViewModel,但我无法与 edmx 模型一起使用