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

时间:2011-09-07 11:16:25

标签: c# entity-framework linq edmx

我收到LINQ查询中标题中显示的错误,该查询包含来自两个不同edmx文件的两个表。这是查询:

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 个答案:

答案 0 :(得分:108)

您必须执行两个数据库查询:

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


您的后续问题:

  

还有其他方法可以使LINQ查询更加优化吗?那是,   在单个LINQ查询本身中执行操作?

为了使您的原始查询成功运行,它必须仅使用单个数据上下文,这意味着所有数据必须来自单个EDMX,这反过来意味着单个连接字符串。有几种方法可以实现这一目标:

  • 如果两个表都在同一个数据库中,请将它们都添加到单个EDMX中。
  • 如果它们位于不同的数据库上但位于同一实例上,则在其中一个数据库上创建一个视图,该数据库从另一个数据库中的表中进行选择,然后将本地表和视图添加到单个EDMX中。
  • 如果他们在不同的实例/服务器上,创建了链接服务器,则在链接服务器上创建表的视图,然后将本地表和视图添加到单个EDMX。

答案 1 :(得分:2)

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

答案 2 :(得分: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
        }
    }