Entity framework 删除所需属性-先删除EF代码

Entity framework 删除所需属性-先删除EF代码,entity-framework,model,attributes,data-annotations,Entity Framework,Model,Attributes,Data Annotations,我有一个抽象类,其中需要属性“CreatedBy”。 除了一个实体(UserProfile本身)之外,几乎所有实体都使用了该选项 如何从UserProfile中删除所需的属性,而不从从EntityBase继承的其他实体中删除它 public abstract class EntityBase: IEntityBase { [Key, Column(Order = 0)] public Guid? Id { get; set; } [Key, Column(Order =

我有一个抽象类,其中需要属性“CreatedBy”。 除了一个实体(UserProfile本身)之外,几乎所有实体都使用了该选项

如何从UserProfile中删除所需的属性,而不从从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; }
}
我试图覆盖我的onmodel创建,但那不起作用。。。有人有什么想法吗

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<UserProfile>().HasOptional(profile => profile.CreatedBy).WithMany();
        modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
    } 
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
基于模型创建(modelBuilder);
modelBuilder.Entity().has可选(profile=>profile.CreatedBy).WithMany();
modelBuilder.Conventions.Remove();
} 
奇怪的是,在我的数据库中,UserProfile表中的CreatedBy_Id和CreatedBy_Version列可以为null


当我在UserProfile表中设置种子时,我得到了每个表的一个验证错误,它说:“CreatedBy字段是必需的。”

有趣的是,数据库生成逻辑被fluent映射覆盖,但验证逻辑不是。这就是流畅的映射和数据注释之间的紧张关系

我想到的第一件事是:给
UserProfile
类一个例外,不要让它继承自
EntityBase
,并给它所需的属性,其中的属性也可以在
EntityBase
中找到

但我敢打赌,其他地方的代码依赖于继承基类或实现接口的类

这里的问题是,
RequiredAttribute
在其规范中(从其基类,
Attribute
)具有
Inherited=true
,因此如果您在
UserProfile
中重写
CreatedBy
,它仍然是必需的

解决方案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
属性,当验证类型为
UserProfile
时,该属性允许
CreatedBy
为空:

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");
    }
}

所以你实际上设计错了

您的需求显然意味着您不应该继承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; }
}
问题解决了


这是正确的方法。实体可以来自任何地方,它们并不总是由用户创建的,因此在设计中提出“所有实体都必须由用户创建”的要求是非常错误的。

解释得很好,是一个很好的解决方案!我会马上测试。试过了,但我还是有同样的问题。你知道其他的解决方法吗?我知道的唯一方法。。。是从我的EntityBase中删除required属性,并在OnModelCreating中为从EntityBase派生的其他每个类添加“HasRequired”。但如果有更简单更好的解决方案,我会改变它。因此,建议仍然很受欢迎。EF似乎可以追溯到基本属性上的属性。即使将
CustomValidationAttribute
(始终返回成功)放在覆盖上也不会删除所需的验证。如果我无法访问
EntityBase
代码,该怎么办?我的意思是:如果
EntityBase
来自一个库,如何解决这个问题?是否有方法删除不需要的属性?如果使用EntityFramework,则可以使用FluentAPI“覆盖”该属性。我必须用我从另一个库中获得的一些属性来实现这一点,我们可以与oracle数据库兼容。FluentAPI优先考虑。仅供参考,只需继承EntityBase并使用new/override重新写入相同的属性,这将擦除属性。