【问题标题】:EF Core Table does not exist when joining from multiple DbContext从多个 DbContext 加入时,EF Core 表不存在
【发布时间】:2018-10-09 17:11:47
【问题描述】:

我在尝试从代表不同数据库的 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 一起获取 Agencies 数据时。

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

会报错

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

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

我们将不胜感激。谢谢

【问题讨论】:

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


    【解决方案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));
    

    【讨论】:

    • 我很抱歉没有按时看到消息,但我后来想出了和你一样的想法,我在上面对 Marcus Höglund 的评论中提到过。感谢您的努力。
    【解决方案2】:

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

    不要使用不同的上下文,而是将实体添加到同一个上下文中(你为什么要为它们设置两个不同的上下文?

    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);
    }
    

    【讨论】:

    • 感谢您的回答。我想在不同的上下文中使用的原因是因为 AgencyApp 在 db2 中,而 Agency 在 db1 中。我尝试了您的第一种方法,将 AgencyApp 添加到同一个 DbContext 中,但发生的情况是,它将 Agency 表视为 db2 的表,应该是 db1。所以抛出错误,db2.agencies' 不存在。
    • @Saya 好的,我还在答案底部添加了针对不同上下文的工作解决方案
    • 第二种解决方案行不通,因为代理机构有超过 500 行数据,并且对于每行数据,您都在循环访问数据库。这不好。我通过为 AgencyApp 表创建一个单独的 DbContext 并从中获取所有这些数据并在 C# 中加入它来解决这个问题。像这样:_dbContextDemo1.Agencies.Where(a =&gt; agencyIds.Contains(a.Id)); 其中的 AgencyIds 是我从 _dbContextDemo2 中获取的 Id。再次感谢您的尝试。
    猜你喜欢
    • 2022-01-24
    • 2021-11-23
    • 2018-11-09
    • 2021-05-09
    • 2023-03-23
    • 1970-01-01
    • 2018-09-22
    • 2021-12-27
    • 1970-01-01
    相关资源
    最近更新 更多