LINQ EF连接查询来自2个不同的数据上下文

5

我正在使用LINQ从EF上下文以及Asp .Net Identity 2.0中检索数据 - 它们都位于同一个MS SQL Server数据库中。

问题是,LINQ将它们视为不同的数据上下文,并且无法处理查询。

"The specified LINQ expression contains references to queries that are associated with different contexts."

我想要实现的是从EF表中返回排过序的前10个项目(在代码片段中我跳过了这一步),先按照ASP .NET身份表中的用户名排序。
我在StackOverflow上看到了几个类似的问题,但是在我的情况下无法应用任何解决方案。
当然,首选的解决方案是不下载整个表格数据,在服务器上进行排序。
有问题的查询如下:
var dbDataSorted = from entry in dbData
        join user in this.UserManager.Users
        on entry.UserId equals new Guid(user.Id)
        orderby user.UserName ascending
        select entry;
return dbDataSorted;

即使两个不同的上下文使用相同的数据库,您也可以通过服务器连接它们。每个上下文都需要知道查询中涉及到的所有表。 - Ben Robinson
一种丑陋的实现方式是编写一个存储过程,将两个数据库表连接起来。其他选项在这个答案中提供。 - Jenish Rabadiya
4个回答

5

在我的情况下,我能够通过使用 AsEnumerable() 方法使其工作。但是在其他情况下可能会有所不同。

针对你的情况:

var dbDataSorted = from entry in dbData.AsEnumerable()
    join user in this.UserManager.Users
    on entry.UserId equals new Guid(user.Id)
    orderby user.UserName ascending
    select entry;
return dbDataSorted;

3
AsEnumerable() 起作用是因为它强制查询的这一部分在客户端执行。只要 dbData 不返回太多记录,它就足以适用于大多数情况。 - Eric J.
1
这个解决了我的问题。我正在从两个不同的dbcontexts加入,一个继承IdentityDbContext,另一个没有,并且需要通过userid连接。谢谢。 - edtruant
1
为了使其正常工作,您需要在连接字符串中启用“MultipleActiveResultSets=true”参数;否则,您将收到“已经有一个与此命令关联的打开的DataReader必须先关闭”的错误。 - edtruant

3

LINQ和EF非常酷。但有时,它的抽象并不能提供你所需的功能。

只需回到基础,手动编写查询,将其放入字符串中,并使用SqlQuery方法在yourcontext.YourDbSet上运行即可完成。

var query = @"SELECT * FROM dbData as entry
              INNER JOIN Users
              ON entry.UserId = Users.Id
              ORDER BY Users.Username";

yourcontext.dbData.SqlQuery(query);

如果提供给您的抽象不符合您的需求,滥用这些抽象以完成奇怪的任务远不如使用更低级别的接口直截了当。


这是我决定使用的解决方案。你的论点很有说服力,它按预期工作。谢谢。 - Quass1m

1
您不能在一个查询中同时使用Linq to Entities和Linq to object。这是因为当您对IQueryable接口的实例进行查询时,查询将被转换为SQL,在SQL中无法使用任何IEnumerable集合。因此,您应该从数据库获取数据(例如dbData.AsEnumerable())。 但是,如果您想在SQL Server端完成所有工作,最简单的方法是创建SQL过程并将用户表作为参数传递。将用户表作为xml传递并在服务器端解析它是最简单的方法。

添加 .AsEnumerable() 会导致从 'System.Collections.Generic.IEnumerable<...>' 转换到 'System.Linq.IQueryable<...>' 的转换错误。也就是说,我不想从数据库下载所有数据,因此这不是我要实现的解决方案。无论如何感谢您的回复。 - Quass1m
我编辑了答案,如果你不想加载所有数据,你应该将你的数据上传到SQL服务器,然后你可以用它做任何你想做的事情。我认为仅通过Linq是不可能完成的。但你可以使用一个存储过程作为实体。 - Pixel

0
如果您正在使用ASP.NET Identity 2的代码优先模式,那么您的DbContext可能继承自IdentityDbContext<>,因此您可以直接从上下文访问Users表。您不需要使用UserManager来访问用户。

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