错误: "指定的LINQ表达式包含与不同上下文相关联的查询的引用"

68

我从包含两个不同edmx文件的两个表的LINQ查询中收到了标题中显示的错误。以下是查询:

var query = (from a in db1.Table1
           join b in db1.Table2 on a.Id equals b.Id
           orderby a.Status
           where b.Id == 1 && a.Status == "new"
           select new
           {
               Id = a.Id,
               CompanyId = (from c in db2.Company
                            where s.Id == a.Id
                            select
                            new { c.CompanyId })
           });

db1db2 是与两个不同 edmx 文件相关联的上下文。我该如何解决这个错误?

3个回答

135

您需要执行两个数据库查询:

var IDs =  (from a in db1.Table1 
            join b in db1.Table2 on a.Id equals b.Id 
            orderby a.Status 
            where b.Id == 1 && a.Status == "new" 
            select new a.Id).ToArray();

var query = from c in db2.Company
            join a in IDs on c.Id equals a.Id
            select new { Id = a.Id, CompanyId = c.CompanyId };
.ToArray() 是关键。它防止 EF 尝试执行组合查询(该查询将失败,因为它使用了两个不同的上下文)。如果您想保持延迟加载,可以使用 .AsEnumerable()。原始查询必须成功运行,这意味着它必须仅使用单个数据上下文,这意味着所有数据必须从单个 EDMX 中可用,从而意味着单个连接字符串。有几种方法可以实现这一点:如果两个表位于同一数据库上,请将它们都添加到一个单独的 EDMX 中;如果它们位于不同的数据库上但在同一实例上,请在其中一个数据库上创建一个视图,该视图从另一个数据库上的表中进行选择,然后将本地表和视图添加到一个单独的 EDMX 中;如果它们位于不同的实例/服务器上,请创建一个链接服务器,然后创建一个在链接服务器上的表的视图,最后将本地表和视图添加到一个单独的 EDMX 中。

Allon,你能否看一下我的问题,https://dev59.com/7YTba4cB1Zd3GeqP7INe?这两个表在同一个EDMX中。非常感谢。 - seebiscuit
1
非常清晰地解释了一种解决方案和可能的替代方案 - 谢谢。 - Andy Brown
最好在这里使用Contains。在旧版EF中,join将生成一个庞大的查询,在后来(核心)版本中不支持。 - Gert Arnold

2

您需要将第二个表格添加到第一个上下文的模型中。如果这在多个数据库中,则需要使用 Linq to Objects join 在客户端进行二次查找。


谢谢您的回复。您能否给我更详细的信息呢? - Ashiq A N
我需要更多细节来了解您为什么要使用多个EDMX文件,以确定该如何进行。 - Jim Wooley

0
你需要手动创建EntityConnection,并从所有.EDMX中填充资源,以便使用它们。 可以通过将连接添加到app.config或程序化地执行来完成此操作。 然后,可以使用准备好的EntityConnection创建DBContext。
方法a)
<add name="MyConnection"
connectionString="metadata=res://*/Entities.ModuleA.csdl|res://*/Entities.ModuleA.ssdl|res://*/Entities.ModuleA.msl|res://*/Entities.ModuleB.csdl|res://*/Entities.ModuleB.ssdl|res://*/Entities.ModuleB.msl;
provider=System.Data.SqlClient;provider connection string=&quot;MyConnectionString&quot;"
providerName="System.Data.EntityClient" />

using (EntityConnection oEntityConnection =
    new EntityConnection("name=MyConnection"))
{
    using(DbContext oDBContext = new DbContext(oEntityConnection))
    {
        //your code - available are entities declared in Entities.ModuleA and Entities.ModuleB
    }
}

方法 b)

 using (EntityConnection oEntityConnection =
        new EntityConnection(new MetadataWorkspace(
        new string [] { 
"res://Entities.ModuleA/", 
"res://Entities.ModuleB/" 
},
        new Assembly[] { 
Assembly.GetAssembly(typeof(Entities.ModuleA.AnyType)),
Assembly.GetAssembly(typeof(Entities.ModuleB.AnyType)) 
}
        )))
    {
        using(DbContext oDBContext = new DbContext(oEntityConnection))
        {
            //your code - available are entities declared in Entities.ModuleA and Entities.ModuleB
        }
    }

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