[英]Where are Entity Framework Core conventions?
使用 EF 6.1+ 有時我們需要添加或刪除現有的內容。 代碼看起來或多或少像:
public class MyContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.AddFromAssembly(Assembly.GetExecutingAssembly());
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
base.OnModelCreating(modelBuilder);
}
}
如何在 EF 核心中做同樣的事情? 模型構建器沒有約定屬性:(
我正在將一些代碼從 EF 移植到 EF Core 2.1+ 並且迫不及待地等待 EF Core 3.0 所以寫了一些擴展方法,它們有點幫助..
public static IEnumerable<IMutableEntityType> EntityTypes(this ModelBuilder builder)
{
return builder.Model.GetEntityTypes();
}
public static IEnumerable<IMutableProperty> Properties(this ModelBuilder builder)
{
return builder.EntityTypes().SelectMany(entityType => entityType.GetProperties());
}
public static IEnumerable<IMutableProperty> Properties<T>(this ModelBuilder builder)
{
return builder.EntityTypes().SelectMany(entityType => entityType.GetProperties().Where(x => x.ClrType == typeof(T)));
}
public static void Configure(this IEnumerable<IMutableEntityType> entityTypes, Action<IMutableEntityType> convention)
{
foreach (var entityType in entityTypes)
{
convention(entityType);
}
}
public static void Configure(this IEnumerable<IMutableProperty> propertyTypes, Action<IMutableProperty> convention)
{
foreach (var propertyType in propertyTypes)
{
convention(propertyType);
}
}
例如,通過這些,您可以編寫類似於 EF 6.1.x 中的約定。
// equivalent of modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.EntityTypes()
.Configure(et => et.Relational().TableName = et.DisplayName());
// Put the table name on the primary key
modelBuilder.Properties()
.Where(x => x.Name == "Id")
.Configure(p => p.Relational().ColumnName = p.DeclaringEntityType.Name + "Id");
// Mark timestamp columns as concurrency tokens
modelBuilder.Properties()
.Where(x => x.Name == "Timestamp")
.Configure(p => p.IsConcurrencyToken = true);
對於 EF Core 3.0,元模型方法略有變化,因此您需要
modelBuilder.EntityTypes()
.Configure(et => et.SetTableName(et.DisplayName()));
modelBuilder.Properties()
.Where(x => x.Name == "Id")
.Configure(p => p.SetColumnName(BaseName(p.DeclaringEntityType.Name) + "Id"));
還沒有檢查過這個效率,但除非你的模型很大,否則應該不會造成問題
這可以使用外鍵、索引等的其他助手進行擴展
看起來它仍然不在 EF Core 2.0 中。 所以這是實現它的一種方法。 我這樣做是為了將一致的行為應用於某些屬性,但要解決您問題中的示例,您可以嘗試以下操作:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// equivalent of modelBuilder.Conventions.AddFromAssembly(Assembly.GetExecutingAssembly());
// look at this answer: https://stackoverflow.com/a/43075152/3419825
// for the other conventions, we do a metadata model loop
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
{
// equivalent of modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
entityType.Relational().TableName = entityType.DisplayName();
// equivalent of modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
// and modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
entityType.GetForeignKeys()
.Where(fk => !fk.IsOwnership && fk.DeleteBehavior == DeleteBehavior.Cascade)
.ToList()
.ForEach(fk => fk.DeleteBehavior = DeleteBehavior.Restrict);
}
base.OnModelCreating(modelBuilder);
}
你應該可以用entityType
做很多事情
為了在 EF Core 5 中設置單數表名,您可以執行以下操作
modelBuilder.Model.GetEntityTypes()
.Configure(et => et.SetTableName(et.DisplayName()));
但是如果你的域中有值對象,它們都將被視為實體類型並在數據庫中創建為表。 如果您的值對象都繼承自ValueObject
類的基本類型,您可以使用以下內容:
modelBuilder.Model.GetEntityTypes()
.Where(x => !x.ClrType.IsSubclassOf(typeof(ValueObject)))
.Configure(et => et.SetTableName(et.DisplayName()));
EF Core 5 的另一個缺點是,當您在實體模型中使用繼承時,設置表名稱會從Table-per-Hierarchy (TPH) 更改為Table-per-Type (TPT)
您可以使用以下替代方法(假設您的實體來自BaseEntity
)
modelBuilder.Model.GetEntityTypes()
.Where(x => x.ClrType.BaseType == typeof(BaseEntity))
.Configure(et => et.SetTableName(et.DisplayName()));
其中 Configure 定義為擴展方法:
public static class ModelBuilderExtensions
{
public static IEnumerable<IMutableEntityType> EntityTypes(this ModelBuilder builder)
{
return builder.Model.GetEntityTypes();
}
public static IEnumerable<IMutableProperty> Properties(this ModelBuilder builder)
{
return builder.EntityTypes().SelectMany(entityType => entityType.GetProperties());
}
public static IEnumerable<IMutableProperty> Properties<T>(this ModelBuilder builder)
{
return builder.EntityTypes().SelectMany(entityType => entityType.GetProperties().Where(x => x.ClrType == typeof(T)));
}
public static void Configure(this IEnumerable<IMutableEntityType> entityTypes, Action<IMutableEntityType> convention)
{
foreach (var entityType in entityTypes)
{
convention(entityType);
}
}
public static void Configure(this IEnumerable<IMutableProperty> propertyTypes, Action<IMutableProperty> convention)
{
foreach (var propertyType in propertyTypes)
{
convention(propertyType);
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.