带有键列表的where语句

时间:2012-08-08 10:12:58

标签: c# linq entity-framework

我的问题是我无法使Where语句与Entity Framework正常工作。

我有一个具有intlong属性的类,用于定义数据库中的一行。我们称之为Id& Parent

public class Update
{
    public long Id { get; set; }
    public int Parent { get; set; }
}

然后我有这些更新的列表,我希望每个数据库行应该匹配列表中的那些更新(两个属性)。

我试过的是我将这些更新转换为匿名类型并尝试仅找到那些具有完美匹配的行:int&长期是一样的。

// anon type
var mapping = updates.Select(o => new { id = o.Id, parent = o.Parent}).ToList();
var results = from fa in Uvw_MyTable 
              // PROBLEMATIC WHERE
              where mapping.Contains(new { id = fa.Id, parent = fa.Parent })
              select new { fa };

但不幸的是我总是收到错误:无法创建“匿名类型”类型的常量值。在此上下文中仅支持原始类型(例如Int32,String和Guid')。

我也试过像这样使用Any

where mapping.Any(a => fa.Id == a.id && fa.Parent == a.parent)

但我得到同样的错误。当我使用Update对象列表时也会发生同样的事情。 无法创建类型为“xxx.Update”的常量值。在此上下文中仅支持原始类型(例如Int32,String和Guid')。

有任何想法如何解决这个问题?

更新

这个完全相同的查询在LINQPad 4中运行良好

更新2

问题是否与此question相关?

更新3

正如Maarten指出的那样,这个问题需要使用不同方法来重新产生相同结果的解决方案。

3 个答案:

答案 0 :(得分:1)

我不确定我是否正确理解了您的代码/问题,但在我看来,这样的事情应该有效:

var results = from fa in Uvw_MyTable 
                    where updates.Any(u => u.Id fa.Id && u.Parent = fa.Parent)
                    select fa; 

我不清楚你对OtherTable的期望行为是什么,但上面的linq表达式的一般形式比你正在使用的表现更有效。

关键是你不需要创建匿名类型来比较多个字段;因此,第一个选择(进入mapping)是多余的。

答案 1 :(得分:1)

您实际上是在代码中执行两个查询。

第一个查询是:

var mapping = updates.Select(o => new { id = o.Id, parent = o.Parent}).ToList();

第二个查询是(好吧,查询没有迭代,所以从技术上讲,查询还没有在这里执行 - 查询错误):

var results = from fa in Uvw_MyTable 
              where mapping.Contains(new { id = fa.Id, parent = fa.Parent })
              select new { fa };

第一个查询是在单个语句中定义和执行的,因为您使用的是ToList()方法。由于现在这是一个对象列表,而不是IQueryable,因此EF无法将其转换为SQL。你必须把它留作IQueryable。如果将其更改为以下内容,则应该可以正常工作。

var mapping = updates
    .Select(o => new { id = o.Id, parent = o.Parent}); // NOT ToList() !!
var results = from fa in Uvw_MyTable 
              where mapping.Contains(new { id = fa.Id, parent = fa.Parent })
              select new { fa };

要解释EF给出的错误 - EF只能将IQueryable转换为SQL,或将原始类型(整数,字符串等)转换为参数。 EF无法将对象转换为SQL,因为它无法以有意义的方式将对象的值传输到数据库。


更新:

第一个查询(我现在看到)根本不是查询,它的源是一个名为updates的变量。如果这是内存中的对象列表,则此查询不能这样翻译,并且您必须重新设计查询(例如,加载Uvw_MyTable是内存)。如果'updates'是IQueryable(来自相同的上下文),那么上面给出的答案应该有效。

答案 2 :(得分:0)

在实体框架或Linq to sql中,linq查询最终将被转换为sql查询。你的linq查询不能转换为SQL查询,因为你正在使用不能转换为sql的类型或类。