实体框架和多个模式

Posted

技术标签:

【中文标题】实体框架和多个模式【英文标题】:Entity Framework and multiple schemas 【发布时间】:2013-01-31 20:57:37 【问题描述】:

我正在尝试设置我的 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());
    

但是,当我尝试执行查询时出现错误:Value cannot be null。它所指的值是_schema1 中的someTable 属性。

答。我该如何解决这个问题?

B.有更好的解决方案吗?

编辑:我想要的是能够编写如下代码 -

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

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

【问题讨论】:

【参考方案1】:

您可以通过Table 属性为每个表指定架构。

[Table(nameof(MyTable1), Schema = "Schema1")]
public class MyTable1  

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

【讨论】:

【参考方案2】:

在对实体框架进行一些研究时,我看到了以下帖子:

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())
    

 

【讨论】:

+1 用于使用 GetOrAdd() 以可读的方式压缩代码。只是想强调一个事实,即使用 .ToList() 合并查询的两个组件中的结果是至关重要的,因为我们正在尝试将来自不同上下文的查询( 【参考方案3】:

尝试改用部分类

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 already contains a definition for 'someTable'。编辑问题以更好地反映我在寻找什么。

以上是关于实体框架和多个模式的主要内容,如果未能解决你的问题,请参考以下文章

具有多个 MySql 模式的实体框架多个 DbContext

实体框架:使用多个架构还是两个不同的数据库?

多对多实体框架和存储库模式插入/更新

实体框架 linq 查询 Include() 多个子实体

具有多个连接条件的实体框架查询

实体框架显示多个同一行