首先删除必需的属性 - EF代码

时间:2014-11-27 20:16:40

标签: entity-framework model attributes data-annotations

我有一个抽象类,其中一个属性" CreatedBy"是必须的。 这用于ALMOST每个实体,只有一个(UserProfile本身)

如何从UserProfile中删除Required属性而不将其从继承自EntityBase的其他实体中删除?

public abstract class EntityBase: IEntityBase
{
    [Key, Column(Order = 0)]
    public Guid? Id { get; set; }

    [Key, Column(Order = 1)]
    public int Version { get; set; }

    [Required]
    public DateTime Created { get; set; }

    [Required]
    public UserProfile CreatedBy { get; set; }

    public bool IsDeleted { get; set; }
}

public class UserProfile: EntityBase
{
    [Required, Index("Username", 3, IsUnique = true), MaxLength(900)]
    public string Username { get; set; }

    [Required, Index("Email", 4, IsUnique = true), MaxLength(900)]
    public string Email { get; set; }
}

我尝试重写我的OnModelCreating,但这不起作用......有人有什么想法吗?

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<UserProfile>().HasOptional(profile => profile.CreatedBy).WithMany();
        modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
    } 

奇怪的是,在我的数据库中,UserProfile表中的CreatedBy_Id和CreatedBy_Version列可以为null。

当我播种UserProfile表时,我得到每个人的验证错误:&#34; CreatedBy字段是必需的。&#34;

2 个答案:

答案 0 :(得分:1)

所以你实际上设计错了。

您的要求显然意味着您不应该从EntityBase继承。你不应该试图强迫这个设计符合你的要求。

改为放松你的EntityBase。

public abstract class EntityBase: IEntityBase
{
    [Key, Column(Order = 0)]
    public Guid? Id { get; set; }

    [Key, Column(Order = 1)]
    public int Version { get; set; }

    [Required]
    public DateTime Created { get; set; }

    public UserProfile CreatedBy { get; set; }

    public bool IsDeleted { get; set; }
}

问题解决了。

这是执行此操作的正确方法。实体可以来自任何地方,它们并非总是由用户创建,因此在您的设计中提出一个要求&#34;所有实体必须由用户制作&#34;是错误的。

答案 1 :(得分:0)

这里有趣的是数据库生成逻辑被流畅的映射覆盖,但验证逻辑不是。它是not the only area,其中流畅的映射和数据注释之间存在紧张关系。

我想到的第一件事是:为UserProfile课程制作一个例外,不要让它从EntityBase继承,并为其提供所需的属性,其中EntityBase中也可以找到属性。

但我敢打赌你在其他地方有代码依赖你的类继承基类或实现接口。

此处的问题是RequiredAttribute在其规范中有Inherited = true(来自其基类Attribute),因此如果您覆盖CreatedBy中的UserProfile它仍然是必需的。

解决方案1 ​​ - 不好

要解决此问题,您可以创建自己的属性,继承RequiredAttribute,并将其设为Inherited = false

[AttributeUsageAttribute(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, 
    AllowMultiple = false,
    Inherited = false)]
public class RequiredInBaseClassAttribute : RequiredAttribute
{
}

现在,如果将此属性放在基类中......

[RequiredInBaseClass]
public virtual UserProfile CreatedBy { get; set; }

并在UserProfile中覆盖它......

public override UserProfile CreatedBy { get; set; }

UserProfile中不再需要它了。嗯,确实如此。 EF似乎追溯了基本属性的属性。

解决方案2

Required属性替换为CustomValidation属性,当验证类型为CreatedBy时,UserProfile允许public abstract class EntityBase: IEntityBase { ... [CustomValidation(typeof(EntityBase), "CreatedByIsValid")] public UserProfile CreatedBy { get; set; } public static ValidationResult CreatedByIsValid(UserProfile value, ValidationContext context) { return value != null || (context.ObjectInstance is UserProfile) ? ValidationResult.Success : new ValidationResult("CreatedBy is required"); } } 为空:

{{1}}