为什么Contains()运算符会降低实体框架的Linq查询?

时间:2012-12-01 05:17:49

标签: performance linq entity-framework .net-4.0 contains

我在实体框架中读到here,如果执行包含操作,则会降低性能:

  

包含在SQL中转换为“WHERE IN”,导致性能下降“

现在我有近10个表有10列,在获取记录时我使用Contains近8列。

我的问题是真的吗?如果是,那替代方案是什么?

1 个答案:

答案 0 :(得分:2)

包含()会严重降低性能。

所以你可以尝试下面提到的解决方案。

我们能够通过添加中间表并从需要使用Contains子句的LINQ查询连接该表来解决EF Contains问题。通过这种方法我们得到了惊人的结果。我们有一个大的EF模型,并且在预编译EF查询时不允许使用“Contains”,对于使用“Contains”子句的查询,我们的性能非常差。

概述:

  1. 在SQL Server中创建一个表 - 例如HelperForContainsOfIntType,其HelperID为Guid数据类型,ReferenceID为int数据类型列。根据需要使用不同数据类型的ReferenceID创建不同的表。

  2. 为EF模型中的HelperForContainsOfIntType和其他此类表创建实体/实体集。根据需要为不同的数据类型创建不同的Entity / EntitySet。

  3. 在.NET代码中创建一个辅助方法,它接受IEnumerable的输入并返回一个Guid。此方法生成一个新的Guid,并将IEnumerable中的值与生成的Guid一起插入HelperForContainsOfIntType。接下来,该方法将此新生成的Guid返回给调用者。要快速插入HelperForContainsOfIntType表,请创建一个存储过程,该过程接受值列表的输入并进行插入。见Table-Valued Parameters in SQL Server 2008 (ADO.NET)。为不同的数据类型创建不同的帮助程序,或创建一个通用的帮助程序方法来处理不同的数据类型。

  4. 创建一个EF编译的查询,类似于下面的内容:

    static Func<MyEntities, Guid, IEnumerable<Customer>> _selectCustomers =
        CompiledQuery.Compile(
            (MyEntities db, Guid containsHelperID) =>
                from cust in db.Customers
                join x in db.HelperForContainsOfIntType on cust.CustomerID equals x.ReferenceID where x.HelperID == containsHelperID
                select cust 
        );
    

    使用要在Contains子句中使用的值调用帮助程序方法,并使Guid在查询中使用。 例如:

    var containsHelperID = dbHelper.InsertIntoHelperForContainsOfIntType(new int[] { 1, 2, 3 });
    var result = _selectCustomers(_dbContext, containsHelperID).ToList();
    

    我是从 Here

    那里得到的