我有一个抽象类,其中一个属性" 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;
答案 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
它仍然是必需的。
要解决此问题,您可以创建自己的属性,继承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似乎追溯了基本属性的属性。
将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}}