EF:使用流畅的API映射基类属性

时间:2017-01-23 12:40:05

标签: c# entity-framework

我首先遇到继承代码问题。 我的基类看起来像这样:

public abstract class BaseEntity
{
    public DateTime? DateCreated { get; set; }
    public string UserCreatedId { get; set; }
    public DateTime? DateModified { get; set; }
    public string UserModifiedId { get; set; }
    public virtual UserState UserCreated { get; set; }
    public virtual UserState UserModified { get; set; }
}

并且我已经继承了它,这给了我一个名为UserCreated_userStateId和UserModified_UserStateId的附加列。所以我尝试这样流畅的API:

modelBuilder.Entity<BaseEntity>().HasOptional(x => x.UserCreated).WithMany().HasForeignKey(x => x.UserCreatedId);
modelBuilder.Entity<BaseEntity>().HasOptional(X => X.UserModified).WithMany().HasForeignKey(x => x.UserModifiedId);

但是这给了我错误:“在模型生成期间检测到一个或多个验证错误:

BaseEntity :: EntityType'BaseEntity'没有定义键。定义此EntityType的键。 BaseEntities:EntityType:EntitySet'BaseEntities'基于类型'BaseEntity',没有定义键。“如何避免定义键并只更改属性的映射?我在派生类中有键。

1 个答案:

答案 0 :(得分:1)

您可以将基类配置包装在泛型方法中,并为每个具体实体类型调用它。

static void ConfigureBaseEntity<TDerived>(EntityTypeConfiguration<TDerived> entityTypeConfiguration) where TDerived : BaseEntity
{
    // your base class configuration
    entityTypeConfiguration.HasOptional(x => x.UserCreated).WithMany().HasForeignKey(x => x.UserCreatedId);
    entityTypeConfiguration.HasOptional(X => X.UserModified).WithMany().HasForeignKey(x => x.UserModifiedId);
}

调用每个具体实体类型

public class DerivedEntity : BaseEntity
{
    public int Id { get; set; }
}

//...
ConfigureBaseEntity(modelBuilder.Entity<DerivedEntity>());

修改

也许Types配置足以达到您的目的。

modelBuilder.Types<BaseEntity>().Configure(entityTypeConfiguration => /* configure using entityTypeConfiguration  */);

否则,如评论所述,您可能需要反思。例如,假设您的所有派生类与BaseEntity类位于同一个程序集中,并且上面的ConfigureBaseEntity方法位于类BaseEntityConfiguration中。

var entityMethod = typeof(DbModelBuilder).GetMethod("Entity");
var configurationMethod = typeof(BaseEntityConfiguration).GetMethod("ConfigureBaseEntity");
foreach (Type t in typeof(BaseEntity).Assembly.GetTypes().Where(x => x.IsSubclassOf(typeof(BaseEntity))))
{
    var configurator = entityMethod.MakeGenericMethod(t).Invoke(modelBuilder, new object[0]);
    configurationMethod.MakeGenericMethod(t).Invoke(null, new object[1] { configurator });
}

但是,如果是我的代码,我宁愿为每个实体类编写一行代码,而不是去动态发现。