C# 实体框架的核心约定在哪里?
使用EF 6.1+时,有时我们需要添加或删除现有约束。代码大致如下所示:C# 实体框架的核心约定在哪里?,c#,entity-framework-core,C#,Entity Framework Core,使用EF 6.1+时,有时我们需要添加或删除现有约束。代码大致如下所示: public class MyContext : DbContext { protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Conventions.AddFromAssembly(Assembly.GetExecutin
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);
}
}
公共类MyContext:DbContext
{
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.AddFromAssembly(Assembly.getExecutionGassembly());
modelBuilder.Conventions.Remove();
modelBuilder.Conventions.Remove();
modelBuilder.Conventions.Remove();
基于模型创建(modelBuilder);
}
}
如何在EF core中实现同样的功能?Modelbuilder没有Conventions属性:(看起来它仍然不在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);
}
模型创建时受保护的覆盖无效(ModelBuilder ModelBuilder)
{
//等效于modelBuilder.Conventions.AddFromAssembly(Assembly.getExecutionGassembly());
//看看这个答案:https://stackoverflow.com/a/43075152/3419825
//对于其他约定,我们执行元数据模型循环
foreach(modelBuilder.Model.GetEntityTypes()中的var entityType)
{
//与modelBuilder.Conventions.Remove()等效;
entityType.Relational().TableName=entityType.DisplayName();
//与modelBuilder.Conventions.Remove()等效;
//和modelBuilder.Conventions.Remove();
entityType.GetForeignKeys()
.Where(fk=>!fk.isoownership&&fk.DeleteBehavior==DeleteBehavior.Cascade)
托利斯先生()
.ForEach(fk=>fk.DeleteBehavior=DeleteBehavior.Restrict);
}
基于模型创建(modelBuilder);
}
您应该能够使用entityType做很多事情,我正在将一些代码从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 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的另一个缺点是,当您在实体模型中使用继承时,设置表名会从(TPH)更改为(TPT)
您可以使用以下替代方法(假设您的实体源自BaseEntity
)
实体框架核心约定在哪里?在未来的某个地方(检查EF核心路线图和积压工作)。计划在3.0版本中使用,请参见.NET Core 3.1——EF Core 5和单复数表名约定请参见此处entityType.Relational().TableName=entityType.DisplayName();如果entityType是“owned”类型,则可能很危险。如果entityType是“owned”类型,则DisplayName()返回所有者表名。这将打乱数据库设计和迁移脚本。@thomasgalliker找到解决方案了吗?同时,我只筛选IsOwned()类型==真。请看一下这行代码:它是否存在于.net core 3.1中?当我尝试执行此操作时,Getting
“IEnumerable”不包含“Configure”的定义。
modelBuilder.Model.GetEntityTypes()
.Configure(et => et.SetTableName(et.DisplayName()));
modelBuilder.Model.GetEntityTypes()
.Where(x => !x.ClrType.IsSubclassOf(typeof(ValueObject)))
.Configure(et => et.SetTableName(et.DisplayName()));
modelBuilder.Model.GetEntityTypes()
.Where(x => x.ClrType.BaseType == typeof(BaseEntity))
.Configure(et => et.SetTableName(et.DisplayName()));