从多个DbContext连接时,EF核心表不存在

时间:2018-10-09 17:11:48

标签: asp.net-core ef-fluent-api ef-core-2.0

当尝试从2个代表不同数据库的DbContext连接2个表时,我遇到了一个问题。

我正在使用Fluent API在2个表之间创建外键关系。 这是Dbcontext的配置和模型。

public class DbContextDemo1: DbContext
{
   public DbSet<Agency> Agencies { get; set; }

   public DbContextDemo1(DbContextOptions<DbContextDemo1> options)
        : base(options)
   {
   }

   protected override void OnModelCreating(ModelBuilder modelBuilder)
   {
        modelBuilder.HasDefaultSchema("db1")
                    .Entity<Agency>()
                    .ToTable("agencies")
                    .HasKey(agency => agency.Id)
                    .HasOne(agency => agency.AgencyApp)
                    .WithOne(app => app.Agency)
                    .HasForeignKey<Agency>(agency => agency.Id);

    }
}

public class DbContextDemo2: DbContext
{
   public DbSet<AgencyApp> AgencyApps { get; set; }

   public DbContextDemo2(DbContextOptions<DbContextDemo2> options)
        : base(options)
   {
   }
   protected override void OnModelCreating(ModelBuilder modelBuilder)
   {
        modelBuilder.HasDefaultSchema("db2")
                    .Entity<AgencyApp>()
                    .ToTable("agenciesapps")
                    .HasKey(app => app .Id)
                    .HasOne(app=> app.Agency)
                    .WithOne(agency => agency.AgencyApp)
                    .HasForeignKey<AgencyApp>(app=> app.AgencyId);         

    }
}

以下是模型:

public class Agency
{
    public Guid Id { get; set; }

    public AgencyApp AgencyApp { get; set; }
}

public class AgencyApp
{
    public Guid Id { get; set; }

    public Guid AgencyId { get; set; }

    public Agency Agency { get; set; }
}

现在,当我尝试与AgencyApp一起获取代理商数据时。

var result = _dbContextDemo1.Agencies.Include(agency => agency.AgencyApplication)

它引发错误

  

“表'db2.agenciesapps'不存在”。

我可以在服务器控制台中看到它正在这两个表之间进行内部联接。

我们将不胜感激。谢谢

2 个答案:

答案 0 :(得分:1)

不支持包含或联接来自不同上下文的表,因为 上下文可以连接到不同的数据库服务器。

不要使用不同的上下文,而是将实体添加到相同的上下文中(为什么还要为它们提供两个不同的上下文?

public class DbContextDemo1: DbContext
{
   public DbSet<Agency> Agencies { get; set; }
   public DbSet<AgencyApp> AgencyApps { get; set; }

   public DbContextDemo1(DbContextOptions<DbContextDemo1> options)
        : base(options)
   {
   }

   protected override void OnModelCreating(ModelBuilder modelBuilder)
   {
        modelBuilder.HasDefaultSchema("db1")
                    .Entity<Agency>()
                    .ToTable("agencies")
                    .HasKey(agency => agency.Id)
                    .HasOne(agency => agency.AgencyApp)
                    .WithOne(app => app.Agency)
                    .HasForeignKey<Agency>(agency => agency.Id);
        modelBuilder.HasDefaultSchema("db1")
                    .Entity<AgencyApp>()
                    .ToTable("agenciesapps")
                    .HasKey(app => app .Id)
                    .HasOne(app=> app.Agency)
                    .WithOne(agency => agency.AgencyApp)
                    .HasForeignKey<AgencyApp>(app=> app.AgencyId); 

    }
}

如果您确实需要在两个不同的上下文中使用它们,则需要将所有实体都提取到内存中,然后将它们结合在一起(这不是一个好主意,因为您需要将所有代理都提取到内存中

var agencies = _dbContextDemo1.Agencies.ToList();
foreach(var agency in agencies)
{
    agency.AgencyApps = _dbContextDemo2.AgencyApps.FirstOrDefault(a=> a.AgencyId == agency.Id);
}

答案 1 :(得分:1)

您不能跨数据库加入。您必须使用两个单独的查询:

var agencies = await _dbContextDemo1.Agencies.ToListAsync();
var agencyApps = await _dbContextDemo2.AgencyApps.Where(x => agencies.Select(a => a.Id).Contains(x.AgencyId)).ToListAsync();

注意:由于您正在选择所有代理,因此从技术上讲,您也可以选择所有代理应用,但是如果最终还要过滤该代理,则按所选代理的ID进行过滤会更好。

然后,您可以将第二个查询中的数据映射到:

agencies.ForEach(x => x.AgencyApp = agencyApps.SingleOrDefault(a => a.AgencyId == x.Id));