正确使用LINQ进行此类查询的方法?

时间:2016-01-20 18:37:04

标签: c# linq

我最初使用foreach循环,然后对循环中的每个元素,我执行LINQ查询,如下所示:

org.springframework.security

然后我像这样修改它:

foreach (MyObject identifier in identifiers.Where(i => i.IsMarkedForDeletion == false))
{
    if (this.MyEntities.Identifiers.Where(pi => identifier.Field1 == pi.Field1 && identifier.Field2 == pi.Field2 && identifier.Field3 == pi.Field3).Any())
    {
        return false;
    }
}

return true;

我的问题是这仍然是使用LINQ的错误方法吗?基本上,我想消除对foreach循环的需要(看起来我应该能够摆脱它),并且还通过不对列表的每个元素执行单独的DB查询来使数据库查询更快。相反,我想对所有元素执行一个查询。谢谢!

3 个答案:

答案 0 :(得分:1)

您可以通过这种方式更改代码,并按预期将其转换为SQL语句。 为了防止转换期间出现运行时错误,最好将DBSet保存到IQueryable变量中; identifiers也应该是IQueryable,因此您应该将代码更改为类似的内容(说实话,Resharper在此简短的labda中转换了您的foreach

IQueryable<MyObject2> identifiers = MyEntities.Identifiers.Where(i => i.IsMarkedForDeletion == false);
IQueryable<MyObject2> ids = MyEntities.Identifiers.AsQueryable();
return identifiers.All(identifier => !ids.Any(pi => identifier.Field1 == pi.Field1 && identifier.Field2 == pi.Field2 && identifier.Field3 == pi.Field3));

如果identifiers在内存集合中,您可以通过这种方式更改代码(希望字段为string):

IQueryable<MyObject2> ids = MyEntities.Identifiers.AsQueryable();
string[] values = identifiers.Where(i => i.IsMarkedForDeletion == false).Select(i => String.Concat(i.Field1, i.Field2, i.Field3)).ToArray();
return !ids.Any(i => values.Contains(i.Field1 + i.Field2 + i.Field3));

答案 1 :(得分:0)

我会按如下方式使用它:

if (identifiers.Where(i => !i.IsMarkedForDeletion &&     
this.MyEntities.Identifiers.Field1 == i.Field1 &&
this.MyEntities.Identifiers.Field2 == i.Field2 && 
this.MyEntities.Identifiers.Field3 == i.Field3).Any()))
{
   return false;
}

return true;

我希望这会有所帮助。即使输入更多内容,使用多个&#39;其中&#39;更容易理解和阅读。语句。

答案 2 :(得分:0)

不幸的是,您的修改版本将以与原始foreach方法完全相同的方式(即多个数据库查询)执行,因为 EF 不支持数据库查询,并且在内存集合中具有连接(除了原始和枚举类型集合),所以如果你尝试最合乎逻辑的方式

bool result = this.MyEntities.Identifiers.Any(pi => identifiers.Any(i =>
    !i.IsMarkedForDeletion &&
    i.Field1 == pi.Field1 && i.Field2 == pi.Field2 && i.Field3 == pi.Field3));

你会得到

  

NotSupportedException :无法创建类型&#39; YourType&#39;的常量值。在此上下文中仅支持原始类型或枚举类型。

EF 执行单个数据库查询的唯一方法是手动为内存集合中的每个项目构建一个Concat的LINQ查询,如下所示

IQueryable<Identifier> query = null;
foreach (var item in identifiers.Where(i => !i.IsMarkedForDeletion))
{
    var i = item;
    var subquery = this.MyEntities.Identifiers.Where(pi => 
        pi.Field1 == i.Field1 && pi.Field2 == i.Field2 && pi.Field3 == i.Field3);
    query = query != null ? query.Concat(subquery) : subquery;
}
bool result = query != null && query.Any();

请参阅Logging and Intercepting Database Operations了解如何监控 EF 操作。