实体框架和多个模式

20

我正在尝试设置我的dbContext,使其能够在单个Oracle数据库中处理多个模式。我不想要一个庞大的dbContext文件,因此我想到了以下解决方案:

public class oraDbContext : DbContext
{
    static oraDbContext() {
        Database.SetInitializer<oraDbContext>(null);
    }

    public oraDbContext(string connName)
        : base("Name=" + connName) { }

    public _schema1 schema1 = _schema1.Instance;
    public _schema2 schema2 = _schema2.Instance;

    protected override void OnModelCreating(DbModelBuilder modelBuilder) {
        schema1.OnModelCreating(modelBuilder);
        schema2.OnModelCreating(modelBuilder);
    }
}

模式文件看起来像这样:

public sealed class _schema1
{
    private static readonly _schema1 instance = new _schema1();

    static _schema1() { }
    private _schema1() { }

    public static _schema1 Instance {
        get {
            return instance;
        }
    }

    public DbSet<someTable> someTable { get; set; }

    internal void OnModelCreating(DbModelBuilder modelBuilder) {
        modelBuilder.Configurations.Add(new someTableMap());
    }
}

然而,当我尝试执行查询时,出现错误:值不能为空。它所指的值是_schema1中someTable属性。

A. 我该如何修复它?

B. 是否有更好的解决方案?

Edit: 我想要的是能够编写以下代码的能力 -

var query1 = from p in db.schema1.someTable
             select p;
var query2 = from p in db.schema2.someTable
             select p;

在我们的数据库中,有几个模式具有完全相同的表,这些表具有相同或几乎相同的列。我不想为每个模式创建单独的dbContext,因为如果我创建一个从5个模式拉取数据的查询,这可能意味着5个不同的连接。如果我用直接的SQL编写此查询,我可以使用单个连接从5个不同的模式中提取数据,这正是我想在这里实现的。

3个回答

14
当我正在研究Entity Framework时,我遇到了以下帖子:

http://romiller.com/2011/05/23/ef-4-1-multi-tenant-with-code-first/

我没有一个单独的dbContext可供使用,但它确实只使用一个连接(这是我不想使用多个dbContext的原因)。在设置以下代码后:

public class oraDbContext : DbContext
{
    static oraDbContext() {
        Database.SetInitializer<oraDbContext>(null);
    }

    private oraDbContext(DbConnection connection, DbCompiledModel model)
        : base(connection, model, contextOwnsConnection: false) { }

    public DbSet<SomeTable1> SomeTable1 { get; set; }
    public DbSet<SomeTable2> SomeTable2 { get; set; }

    private static ConcurrentDictionary<Tuple<string, string>, DbCompiledModel> modelCache = new ConcurrentDictionary<Tuple<string, string>, DbCompiledModel>();

    public static oraDbContext Create(string schemaName, DbConnection connection) {
        var compiledModel = modelCache.GetOrAdd(
            Tuple.Create(connection.ConnectionString, schemaName),
            t =>
            {
                var builder = new DbModelBuilder();
                builder.Configurations.Add<SomeTable1>(new SomeTable1Map(schemaName));
                builder.Configurations.Add<SomeTable2>(new SomeTable2Map(schemaName));

                var model = builder.Build(connection);
                return model.Compile();
            });

        return new oraDbContext(connection, compiledModel);
    }
}

当然,这需要我的映射文件设置如下:
public class DailyDependencyTableMap : EntityTypeConfiguration<DailyDependencyTable>
{
    public SomeTableMap(string schemaName) {
        this.ToTable("SOME_TABLE_1", schemaName.ToUpper());

        //Map other properties and stuff
    }
}

编写使用多个模式的查询有点烦人,但目前它做到了我需要的功能:

using (var connection = new OracleConnection("a connection string")) {
    using (var schema1 = oraDbContext.Create("SCHEMA1", connection))
    using (var schema2 = oraDbContext.Create("SCHEMA2", connection)) {

        var query = ((from a in schema1.SomeTable1 select new { a.Field1 }).ToList())
             .Concat((from b in schema2.SomeTable1 select new { b.Field1 }).ToList())
    }
}

 


在编写代码时,使用GetOrAdd()可以使代码更加简洁易读。需要强调的是,在合并查询结果的两个组件时,使用.ToList()非常重要,因为我们正在尝试将来自不同上下文的查询组合起来(<- 使用实体框架和其他orm时,此类操作不能直接应用于数据库)。 - XDS

9
您可以通过Table属性为每个表指定模式。
[Table(nameof(MyTable1), Schema = "Schema1")]
public class MyTable1 { }

[Table(nameof(MyTable2), Schema = "Schema2")]
public class MyTable2 { }

1
尝试使用部分类代替。
public partial class oraDbContext : DbContext
{
    static oraDbContext() {
        Database.SetInitializer<oraDbContext>(null);
    }

    public oraDbContext(string connName)
        : base("Name=" + connName) { }

    protected override void OnModelCreating(DbModelBuilder modelBuilder) {
        schema1(modelBuilder);
        schema2(modelBuilder);
    }
}

public partial class oraDbContext : DbContext
{
    public DbSet<someTable> someTable { get; set; }
    void schema1(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new someTableMap());
    }
}

今天我终于有机会测试了一下,但是出现了一个错误:oraDbContext已经包含了“someTable”的定义。 我修改了问题以更好地反映我正在寻找的内容。 - Kittoes0124

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接