LINQ 异常:“不支持使用本地集合的查询。”但不使用本地集合

发布于 2024-10-07 10:02:33 字数 979 浏览 3 评论 0原文

以 AdventureWorks 数据库的 Products 表为例,我创建了一个 DBML 并扩展了 DataContext 的属性以包含一个新属性:

partial class AdventureWorksDataContext
{
  public IQueryable<Product> FinishedProducts
  {
    get { return Products.Where(p => p.FinishedGoodsFlag); }
  }
}

Products 属性是生成的 DataContext 的一部分,我所做的只是添加一个Where from the Table< ;产品>所以它返回一个 IQueryable。

现在,当尝试像这样查询它时,问题就出现了(愚蠢的示例,但应该显示问题):

var queryFinishedProducts = datacontext.FinishedProducts.Where(fp => fp.ProductID == datacontext.FinishedProducts. Max(p => p.ProductID));

迭代此查询会导致“不支持使用本地集合的查询”异常。我不明白为什么当没有使用本地集合时它会抛出该错误。如果我针对普通的产品表(即 Table)运行它:

var queryProducts = datacontext.FinishedProducts.Where(fp => fp.ProductID == datacontext.Products .Max(p => p.ProductID));

...工作正常。唯一的区别是我向 Table 添加了一个Where,并将其作为 IQueryable 返回。

有人有什么想法吗?

Using the AdventureWorks database's Products table as the example, I have created a DBML and extended the properties of the DataContext to include a new property:

partial class AdventureWorksDataContext
{
  public IQueryable<Product> FinishedProducts
  {
    get { return Products.Where(p => p.FinishedGoodsFlag); }
  }
}

The Products property is part of the generated DataContext and all I've done is add a Where from the Table<Product> so it returns an IQueryable.

Now, the problem comes in when trying to query it like this (dumb example but one that should show the problem):

var queryFinishedProducts = datacontext.FinishedProducts.Where(fp => fp.ProductID == datacontext.FinishedProducts.Max(p => p.ProductID));

Iterating this query results in "Queries with local collections are not supported" exception. I don't understand why it would throw that error when there are no local collections being used. If I run it against the normal Products table (which is a Table<Product>):

var queryProducts = datacontext.FinishedProducts.Where(fp => fp.ProductID == datacontext.Products.Max(p => p.ProductID));

...it works fine. The only difference is that I added a Where to the Table<Product> and returned it as an IQueryable<Product>.

Anyone have any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

离不开的别离 2024-10-14 10:02:33

这是一种可行的方法:

var max = datacontext.FinishedProducts.Max(p => p.ProductID);
var queryFinishedProducts = datacontext.FinishedProducts
                                       .Where(fp => fp.ProductID == max);

或者假设 ProductID 是唯一的,尝试按如下方式重写您的查询:

var queryProducts = datacontext.FinishedProducts
                               .OrderByDescending(p => p.ProductID)
                               .First();

Here's one approach that should work:

var max = datacontext.FinishedProducts.Max(p => p.ProductID);
var queryFinishedProducts = datacontext.FinishedProducts
                                       .Where(fp => fp.ProductID == max);

Or assuming that ProductID is unique try rewriting your query as follows:

var queryProducts = datacontext.FinishedProducts
                               .OrderByDescending(p => p.ProductID)
                               .First();
我不会写诗 2024-10-14 10:02:33

我能够重现这种行为。以下是反射器中需要查看的更多类型:

System.Data.Linq.SqlClient.SqlBinder.Visitor
System.Data.Linq.SqlClient.SqlVisitor

基于此堆栈跟踪。

at System.Data.Linq.SqlClient.SqlBinder.Visitor.ConvertToFetchedSequence(SqlNode node)
at ..SqlBinder.Visitor.VisitAlias(SqlAlias a)
at System.Data.Linq.SqlClient.SqlVisitor.Visit(SqlNode node)
at ..SqlVisitor.VisitSource(SqlSource source)
at ..SqlBinder.Visitor.VisitSelect(SqlSelect select)
at ..SqlVisitor.Visit(SqlNode node)
at ..SqlBinder.Visitor.VisitAlias(SqlAlias a)
at ..SqlVisitor.Visit(SqlNode node)
at ..SqlVisitor.VisitSource(SqlSource source)
at ..SqlBinder.Visitor.VisitSelect(SqlSelect select)
at ..SqlVisitor.Visit(SqlNode node)
at ..SqlVisitor.VisitSequence(SqlSelect sel)
at ..SqlVisitor.VisitScalarSubSelect(SqlSubSelect ss)
at ..SqlVisitor.VisitSubSelect(SqlSubSelect ss)
at ..SqlBinder.Visitor.VisitSubSelect(SqlSubSelect ss)

我想知道为什么 Table 类型的属性的处理方式与 IQueryable 甚至 ITable 类型的属性不同。属性的实现并不重要,返回类型很重要。


IQueryable 类型的属性的处理方式肯定与 IQueryable 类型的本地作用域变量不同,query1

IQueryable<Customer> query1 =
  myDC.Customers.Where(c => c.ID == myDC.CoolCustomers.Max(c2 => c2.ID));

IQueryable<Customer> query2 =
  myDC.Customers.Where(c => c.ID == myDC.Customers.Where(c2 => c2.Flag).Max(c2 => c2.ID));

IQueryable<Customer> subQuery = myDC.CoolCustomers;
IQueryable<Customer> query3 =
  myDC.Customers.Where(c => c.ID == subQuery.Max(c2 => c2.ID));

表现出原始行为(异常、本地序列)。

query2 生成此 sql - 不太理想。

SELECT [t0].[ID], [t0].[Flag]
FROM [Customer] AS [t0]
OUTER APPLY (
    SELECT MAX([t1].[ID]) AS [value]
    FROM [Customer] AS [t1]
    WHERE [t1].[Flag] = 1
    ) AS [t2]
WHERE [t0].[ID] = [t2].[value]

query3 在查询翻译期间过度急切地发出子查询,然后对主查询进行第二次往返。

I was able to reproduce this behavior. Here's a couple more types to look at in reflector:

System.Data.Linq.SqlClient.SqlBinder.Visitor
System.Data.Linq.SqlClient.SqlVisitor

Based on this stack trace.

at System.Data.Linq.SqlClient.SqlBinder.Visitor.ConvertToFetchedSequence(SqlNode node)
at ..SqlBinder.Visitor.VisitAlias(SqlAlias a)
at System.Data.Linq.SqlClient.SqlVisitor.Visit(SqlNode node)
at ..SqlVisitor.VisitSource(SqlSource source)
at ..SqlBinder.Visitor.VisitSelect(SqlSelect select)
at ..SqlVisitor.Visit(SqlNode node)
at ..SqlBinder.Visitor.VisitAlias(SqlAlias a)
at ..SqlVisitor.Visit(SqlNode node)
at ..SqlVisitor.VisitSource(SqlSource source)
at ..SqlBinder.Visitor.VisitSelect(SqlSelect select)
at ..SqlVisitor.Visit(SqlNode node)
at ..SqlVisitor.VisitSequence(SqlSelect sel)
at ..SqlVisitor.VisitScalarSubSelect(SqlSubSelect ss)
at ..SqlVisitor.VisitSubSelect(SqlSubSelect ss)
at ..SqlBinder.Visitor.VisitSubSelect(SqlSubSelect ss)

I wonder why a property of type Table<T> is treated differently than a property of type IQueryable<T> or even ITable<T>. The implementation of the property doesn't matter, the return type matters.


A property of type IQueryable<T> is definately treated differently than a locally scoped variable of type IQueryable<T>

IQueryable<Customer> query1 =
  myDC.Customers.Where(c => c.ID == myDC.CoolCustomers.Max(c2 => c2.ID));

IQueryable<Customer> query2 =
  myDC.Customers.Where(c => c.ID == myDC.Customers.Where(c2 => c2.Flag).Max(c2 => c2.ID));

IQueryable<Customer> subQuery = myDC.CoolCustomers;
IQueryable<Customer> query3 =
  myDC.Customers.Where(c => c.ID == subQuery.Max(c2 => c2.ID));

query1 exhibits the original behavior (exception, local sequences).

query2 generates this sql - less than ideal.

SELECT [t0].[ID], [t0].[Flag]
FROM [Customer] AS [t0]
OUTER APPLY (
    SELECT MAX([t1].[ID]) AS [value]
    FROM [Customer] AS [t1]
    WHERE [t1].[Flag] = 1
    ) AS [t2]
WHERE [t0].[ID] = [t2].[value]

query3 over-eagerly issues the subquery during query translation, then makes a second roundtrip for the main query.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文