所以我在我的应用程序的核心项目中有一个删除并重新创建设置,该项目由我的所有应用程序使用。我的模型变化足够大,我需要这个drop并在每次我回收我的应用程序池时重新创建数据库表(app现在处于快速开发阶段。)问题是如果2个项目同时启动,删除并重新创建彼此的步骤,并多次丢失表。
我需要一种方法来防止在运行时根据条件创建模型。我试过了:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
if (condition)
return;
//...
base.OnModelCreating(modelBuilder);
}
但这不起作用......表仍在创建中。我怎么能这样做?
答案 0 :(得分:1)
对您的情况不太确定。
出于开发目的,您可以为表使用不同的模式。
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.HasDefaultSchema("applicationX");
}
如果无法做到这一点,您可以为实体添加后缀/前缀表名称。
如果您需要两个应用程序共享表(数据),您可以在共享相同模型构建代码的任何应用程序中组合所有数据库。
然后,当然,您必须以某种方式为您的数据库娱乐代码(https://github.com/aspnet/EntityFramework/issues/3042)创建“关键部分”,使用互斥锁或/并将其组合,例如使用您自己的数据库中的锁同步对象(表)。
如果需要动态构建模型(数据库),例如,使用依赖注入在单个DB上下文中动态构建模型:
/// <summary>
/// Formalization of entity framework DbContext model creation <see cref="DbContext.OnModelCreating"/>
/// </summary>
/// <remarks>
/// The reason for this explicit interface of the <see cref="DbContext.OnModelCreating"/> is to make compositions of several model builders into one
/// </remarks>
public interface IEntityFrameworkModelBuilder
{
void BuildModel(ModelBuilder modelBuilder);
}
public abstract class DbContextBase : DbContext
{
protected DbContextBase(DbContextOptions options, IEntityFrameworkModelBuilder modelBuilder) : base(options)
{
_modelBuilder = modelBuilder;
}
public virtual IEntityFrameworkModelBuilder ModelBuilder
{
get { return _modelBuilder ?? (_modelBuilder = new DefaultSchemaEntityFrameworkModelBuilder("dbo")); }
protected set { _modelBuilder = value; }
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
ModelBuilder.BuildModel(modelBuilder);
}
}
当然,你可以创建例如IEntityFrameworkModelBuilder的composit模式类:
/// <summary>
/// The composition of <see cref="IEntityFrameworkModelBuilder"/> used to construct <see cref="DbContext"/> model creation from several modules (tests).
/// </summary>
/// <seealso cref="DbContextOnModelCreatingAdaptingModelBuilder"/>
public class EntityFrameworkModelBuilderComposition : IEntityFrameworkModelBuilder, IList<IEntityFrameworkModelBuilder>
{
private readonly IList<IEntityFrameworkModelBuilder> _builders;
public EntityFrameworkModelBuilderComposition() : this(new IEntityFrameworkModelBuilder[0])
{}
public EntityFrameworkModelBuilderComposition(params IEntityFrameworkModelBuilder[] builders)
{
_builders = new List<IEntityFrameworkModelBuilder>(builders);
}
/// <summary>
/// Constructor to take list of builders as underlaying list so it is initialized with these builders and sharing the same reference.
/// </summary>
/// <param name="builders"></param>
public EntityFrameworkModelBuilderComposition(IList<IEntityFrameworkModelBuilder> builders)
{
_builders = builders ?? new List<IEntityFrameworkModelBuilder>();
}
public virtual void BuildModel(ModelBuilder modelBuilder)
{
foreach (var b in _builders)
{
b.BuildModel(modelBuilder);
}
}
}
只需添加,迟早会发现有用的内容:
/// <summary>
/// The <see cref="IEntityFrameworkModelBuilder"/> implementation of a building model on the base of <see cref="DbContext"/> instance calling its <see cref="DbContext.OnModelCreating"/> protected method.
/// </summary>
/// <seealso cref="DbContextOnModelCreatingAdaptingModelBuilder"/>
/// <seealso cref="EntityFrameworkModelBuilderComposition"/>
public class DbContextOnModelCreatingAdaptingModelBuilder : IEntityFrameworkModelBuilder
{
private readonly Func<DbContext> _dbContextFactoryMethod;
public DbContextOnModelCreatingAdaptingModelBuilder(Func<DbContext> dbContextFactoryMethod)
{
_dbContextFactoryMethod = dbContextFactoryMethod;
}
public void BuildModel(ModelBuilder modelBuilder)
{
using (var dbContext = _dbContextFactoryMethod())
{
MethodInfo onModelCreating = dbContext.GetType().GetMethod("OnModelCreating", BindingFlags.NonPublic | BindingFlags.Instance);
onModelCreating.Invoke(dbContext, new object[] {modelBuilder});
}
}
}
当然,所有提到的点都可以/必须结合起来以获得所需的行为。但目前尚不清楚,您如何评估模型差异,
我的模型变化足够大,我需要这个drop并重新创建
完全是指
删除并重新创建彼此的步骤,并多次丢失表
答案 1 :(得分:0)
可悲的是,根据微软的说法,似乎没有办法做到这一点:https://github.com/aspnet/EntityFramework/issues/6346