Linq2Sql - >根据本地值集搜索数据库 - “不支持使用本地集合进行查询”

时间:2009-08-06 17:26:58

标签: c# linq linq-to-sql

我正在与Linq2SQL碰壁。我喜欢它,它的灵活性令人惊叹,但我遇到了有趣的挂断。我希望它只是缺乏对它的了解,而且确实有一个解决方案。举个例子......像这样的linq2sql查询:

//一些本地的ID集合

var terminalID = new List<int>(){1, 2, 3, 4, 5};

// Linq声明的一部分:

queryDataIDs.Where(q => q.DataEventKeyID == 2 && terminalID.Contains((int)q.ValueDecimal));

将导致错误@ runtime

"NotSupportedException was unhandled"
"Queries with local collections are not supported"

堆栈:

at System.Data.Linq.SqlClient.SqlBinder.Visitor.ConvertToFetchedSequence(SqlNode node)
   at System.Data.Linq.SqlClient.SqlBinder.Visitor.VisitAlias(SqlAlias a)
   at System.Data.Linq.SqlClient.SqlVisitor.Visit(SqlNode node)
   at System.Data.Linq.SqlClient.SqlVisitor.VisitSource(SqlSource source)
   at System.Data.Linq.SqlClient.SqlBinder.Visitor.VisitSelect(SqlSelect select)
   at System.Data.Linq.SqlClient.SqlVisitor.Visit(SqlNode node)
   at System.Data.Linq.SqlClient.SqlBinder.Visitor.VisitAlias(SqlAlias a)
   at System.Data.Linq.SqlClient.SqlVisitor.Visit(SqlNode node)
   at System.Data.Linq.SqlClient.SqlVisitor.VisitSource(SqlSource source)
   at System.Data.Linq.SqlClient.SqlBinder.Visitor.VisitSelect(SqlSelect select)
   at System.Data.Linq.SqlClient.SqlVisitor.Visit(SqlNode node)
   at System.Data.Linq.SqlClient.SqlVisitor.VisitSequence(SqlSelect sel)
   at System.Data.Linq.SqlClient.SqlVisitor.VisitExists(SqlSubSelect sqlExpr)
   at System.Data.Linq.SqlClient.SqlVisitor.VisitSubSelect(SqlSubSelect ss)
   at System.Data.Linq.SqlClient.SqlBinder.Visitor.VisitSubSelect(SqlSubSelect ss)
   at System.Data.Linq.SqlClient.SqlVisitor.Visit(SqlNode node)
   at System.Data.Linq.SqlClient.SqlBinder.Visitor.VisitExpression(SqlExpression expr)
   at System.Data.Linq.SqlClient.SqlBinder.Visitor.VisitBinaryOperator(SqlBinary bo)
   at System.Data.Linq.SqlClient.SqlVisitor.Visit(SqlNode node)
   at System.Data.Linq.SqlClient.SqlBinder.Visitor.VisitExpression(SqlExpression expr)
   at System.Data.Linq.SqlClient.SqlBinder.Visitor.VisitSelect(SqlSelect select)
   at System.Data.Linq.SqlClient.SqlVisitor.Visit(SqlNode node)

我做错了什么? Google / Bing不会为此报告许多解决方案,但它似乎很直接。

这不是解决方案 - 它不起作用。相同的错误。

Working around LinqToSQls "queries with local collections are not supported" exception

4 个答案:

答案 0 :(得分:1)

对不起伙计们,我确实找到了问题所在。问题不是我上面发布的查询,而是来自我在下一个查询中的部分查询中使用它。例如。那个问题让我得到了我需要的ID列表。我在下面使用它是这样的:

where queryDataIDs.Select(x => x.ID).Contains(dataEvent.DataEventID)

但是,它会出错。我试图让它在查询#2的where语句中进行子查询。

如果我这样做:

where queryDataIDs.ToList().Select(x => x.ID).Contains(dataEvent.DataEventID)

没有问题。但问题是它将一个查询转换为两个查询(在sql server级别)。性能很好,因为它在一个连接中处理,但我希望得到一个很好的单个查询来运行。

所以,我为发布错误的代码部分而道歉。似乎Linq2Sql无法像我想做的那样创建一个子查询,但那是一个小小的挫折。

答案 1 :(得分:0)

我无法重现你的问题。我尝试使用对象实例化来查看您的Linq语法是否存在问题,但这有效。所以,我创建了一个Sql表: TestQueryData(DataEventKeyID:int(pk),ValueDecimal:decimal(5,3))

然后我用这个类/表创建了一个LinqToSql dbml,你的代码仍然产生了一个结果。我将布尔值更改为另一个Where语句,并且它在两种情况下仍然有效。

/* // This all works
             IQueryable<QueryData> queryDataIDs = new QueryData[]{ 
                new QueryData{DataEventKeyID = 1, ValueDecimal = 2.2m },
                new QueryData{DataEventKeyID = 2, ValueDecimal = 2.3m },
                new QueryData{DataEventKeyID = 3, ValueDecimal = 2.4m },
                new QueryData{DataEventKeyID = 4, ValueDecimal = 2.5m },
                new QueryData{DataEventKeyID = 5, ValueDecimal = 2.6m },
                new QueryData{DataEventKeyID = 6, ValueDecimal = 2.7m },
                new QueryData{DataEventKeyID = 7, ValueDecimal = 2.8m },
                new QueryData{DataEventKeyID = 8, ValueDecimal = 2.9m }
            }.AsQueryable();

            // some local collection of ids 
            var terminalID = new List<int>(){1, 2, 3, 4, 5};

            // a part of a Linq statement: 
            var selectedValues = queryDataIDs
                .Where(q => q.DataEventKeyID == 2)
                .Where(q => terminalID.Contains((int)q.ValueDecimal)); */

            TestQueryDataDataContext db = new TestQueryDataDataContext();
            IQueryable<TestQueryData> queryDataIDs = db.TestQueryDatas;
            var terminalID = new List<int>() { 1, 2, 3, 4, 5 };
            var selectedValues = queryDataIDs
                .Where(q => q.DataEventKeyID == 2)
                .Where(q => terminalID.Contains((int)q.ValueDecimal));

我假设您的列表是Ints的通用列表,因为它没有显示在您的帖子中。此外,如果您的数据库表允许ValueDecimal的空值,则必须在尝试强制转换为int之前检查它。

答案 2 :(得分:0)

编辑:看起来你正试图查询queryDataIDs,那是什么?您想查询DataContextInstance.LinqToSqlCollection

var myResults = (
     from q in DataContextInstance.LinqToSqlCollection
     where q.DataEventKey == 2 && terminalID.Contains((int)q.ValueDecimal) 
     select q);

或者如果您只想要ID,请将其更改为选择q.DataEventKey而不是选择q

答案 3 :(得分:-1)

您的问题是您正在尝试执行包含“动态”局部变量的SQL查询。 事实是,linq2sql不能像这样进行查询:

select * from table
where id in (--list of ids here referenced from a local variable--)

首先,您应该从数据库中的表中收集列表:

IQueryable<int> terminalID = db.terminals.where(p=>p.id<=5).select(x=>x.id);

然后继续查询:

queryDataIDs.Where(q => q.DataEventKeyID == 2 && terminalID.Contains((int)q.ValueDecimal));

希望有所帮助