如何在EF7或EF核心

时间:2016-05-12 07:44:28

标签: entity-framework

我的数据库具有不同的架构,具体取决于运行时的用户选择。

我的代码如下:

public partial class FashionContext : DbContext
{
    private string _schema;

    public FashionContext(string schema) : base()
    {
        _schema = schema;
    }

    public virtual DbSet<Style> Styles { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder options)
    {
        options.UseSqlServer(@"Server=.\sqlexpress;Database=inforfashionplm;Trusted_Connection=True;");
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Style>()
            .ToTable("Style", schema: _schema);
    }
}

经过测试。我用'schema1'创建了一个上下文实例。 到现在为止还挺好。

但是当我用不同的模式'schema2'创建另一个上下文实例时,模式仍在'schema1'上的结果数据。

以下是实施:

using (var db = new FashionContext("schema1"))
        {
            foreach (var style in db.Styles)
            {
                Console.WriteLine(style.Name);
            }
        }

        Console.ReadLine();
        Console.Clear();

        using (var db = new FashionContext("schema2"))
        {
            foreach (var style in db.Styles)
            {
                Console.WriteLine(style.Name);
            }
        }

        Console.ReadLine();

后来我注意到OnModelCreating只被调用一次,因此在创建相同连接字符串的新上下文实例时永远不会再调用它。

是否可以在运行时使用动态模式?注意:这可以在EF6中使用

3 个答案:

答案 0 :(得分:2)

您可以在外部构建模型,并使用DbContext

将其传递到DbContextOptionsBuilder.UseModel()

另一种(更高级的)替代方法是替换IModelCacheKeyFactory以考虑架构。

答案 1 :(得分:0)

上面已经提到了一种可能的方法,但只是简要介绍一下,因此我将尝试通过示例进行解释。

您应该覆盖默认的 ModelCacheKeyFactory ModelCacheKey

ModelCachekeyFactory.cs

internal sealed class CustomModelCacheKeyFactory<TContext> : ModelCacheKeyFactory
    where TContext : TenantDbContext<TContext>
{
    public override object Create(DbContext context)
    {
        return new CustomModelCacheKey<TContext>(context);
    }

    public CustomModelCacheKeyFactory([NotNull] ModelCacheKeyFactoryDependencies dependencies) : base(dependencies)
    {
    }
}

ModelCacheKey.cs,请查看Equals和GetHashCode重写的方法,它们不是最好的方法,应加以改进。

internal sealed class ModelCacheKey<TContext> : ModelCacheKey where TContext : TenantDbContext<TContext>
{
    private readonly string _schema;
    public ModelCacheKey(DbContext context) : base(context)
    {
        _schema = (context as TContext)?.Schema;
    }

    protected override bool Equals(ModelCacheKey other)
    {
        return base.Equals(other) && (other as ModelCacheKey<TContext>)?._schema == _schema;
    }

    public override int GetHashCode()
    {
        var hashCode = base.GetHashCode();
        if (_schema != null)
        {
            hashCode ^= _schema.GetHashCode();
        }

        return hashCode;
    }
}

注册DI。

builder.UseSqlServer(dbConfiguration.Connection)
.ReplaceService<IModelCacheKeyFactory, CustomModelCacheKeyFactory<CustomContext>>();

上下文示例。

public sealed class CustomContext : TenantDbContext<CustomContext>
{
    public CustomContext(DbContextOptions<CustomContext> options, string schema) : base(options, schema)
    {
    }
}

答案 2 :(得分:-1)

我找到了一种在每个上下文创建时重新创建已编译模型的方法。

public partial class MyModel : DbContext {

    private static DbConnection _connection
    {
        get
        {
            //return a new db connection
        }
    }

    private static DbCompiledModel _model
    {
        get
        {
            return CreateModel("schema name");
        }
    }

    public MyModel()
        : base(_connection, _model, false)
    {
    }

    private static DbCompiledModel CreateModel(string schema)
    {
        var modelBuilder = new DbModelBuilder();
        modelBuilder.HasDefaultSchema(schema);
        modelBuilder.Entity<entity1>().ToTable(schema + ".entity1");
        var builtModel = modelBuilder.Build(_connection);
        return builtModel.Compile();
    }
}