Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在大型列表的实体框架中使用IList.Contains(item.Id)的替代方法?_C#_Sql Server 2005_Entity Framework_Linq To Entities - Fatal编程技术网

C# 在大型列表的实体框架中使用IList.Contains(item.Id)的替代方法?

C# 在大型列表的实体框架中使用IList.Contains(item.Id)的替代方法?,c#,sql-server-2005,entity-framework,linq-to-entities,C#,Sql Server 2005,Entity Framework,Linq To Entities,除了使用.Contains()选择实体框架中存在于指定列表中的对象之外,还有其他方法吗Contains()如果列表很小,效果会很好,但是一旦您开始获得几千个项目,性能就会很差 return (from item in context.Accounts where accountIdList.Contains(item.AccountId) select item).ToList(); 我正在使用EF4.0、.NETFramework4.0和SQLServer20

除了使用
.Contains()
选择实体框架中存在于指定列表中的对象之外,还有其他方法吗
Contains()
如果列表很小,效果会很好,但是一旦您开始获得几千个项目,性能就会很差

return (from item in context.Accounts
        where accountIdList.Contains(item.AccountId)
        select item).ToList();

我正在使用EF4.0、.NETFramework4.0和SQLServer2005。我也不反对SQL解决方案,因为EF生成的查询只需一秒钟就可以在SQL上运行大约10000个项目。

将信息读入内存然后进行搜索是否可行


我发现,在大多数情况下,如果可以将所有数据读入内存,然后进行查找,那么您就需要处理大量数据。它的查找速度要快得多。

包含的
已被转换为大量的
WHERE in
SQL语句,因此这不是一个真正的问题。但是,您不应该急切地评估查询,因为每次调用该方法时都会执行查询。利用linq to实体的特性,并在实际迭代查询时对其进行计算。

我发现了一个替代方法,它使用SQL存储过程和参数的逗号分隔字符串在大约一秒钟内运行。比使用
.Contains()

它使用以下代码从我的代码运行:

string commaDelmitedList = string.Join(",", accountIdList);
return context.GetAccountsByList(commaDelmitedList).ToList();
StoredProcess(简化)如下所示:

SELECT *
FROM   Accounts as T1 WITH (NOLOCK)
INNER JOIN (
    SELECT Num FROM dbo.StringToNumSet(@commaDelimitedAccountIds, ',')
) as [T2] ON [T1].[AccountId] = [T2].[num]
CREATE FUNCTION [dbo].[StringToNumSet] (
 @TargetString  varchar(MAX),
 @SearchChar varchar(1)
 )
RETURNS @Set TABLE (
 num int not null
 )
AS
BEGIN
 DECLARE @SearchCharPos  int,  @LastSearchCharPos int
 SET @SearchCharPos = 0
 WHILE 1=1
 BEGIN
  SET @LastSearchCharPos = @SearchCharPos
  SET @SearchCharPos = CHARINDEX( @SearchChar, @TargetString, @SearchCharPos + 1 )
  IF @SearchCharPos = 0
  BEGIN
   INSERT @Set( num ) VALUES ( SUBSTRING( @TargetString, @LastSearchCharPos + 1, DATALENGTH( @TargetString ) ) )
   BREAK
  END
  ELSE
   INSERT @Set( num ) VALUES ( SUBSTRING( @TargetString, @LastSearchCharPos + 1, @SearchCharPos - @LastSearchCharPos - 1 ) )
 END
 RETURN
END
用户定义的函数dbo.StringToNumSet()如下所示:

SELECT *
FROM   Accounts as T1 WITH (NOLOCK)
INNER JOIN (
    SELECT Num FROM dbo.StringToNumSet(@commaDelimitedAccountIds, ',')
) as [T2] ON [T1].[AccountId] = [T2].[num]
CREATE FUNCTION [dbo].[StringToNumSet] (
 @TargetString  varchar(MAX),
 @SearchChar varchar(1)
 )
RETURNS @Set TABLE (
 num int not null
 )
AS
BEGIN
 DECLARE @SearchCharPos  int,  @LastSearchCharPos int
 SET @SearchCharPos = 0
 WHILE 1=1
 BEGIN
  SET @LastSearchCharPos = @SearchCharPos
  SET @SearchCharPos = CHARINDEX( @SearchChar, @TargetString, @SearchCharPos + 1 )
  IF @SearchCharPos = 0
  BEGIN
   INSERT @Set( num ) VALUES ( SUBSTRING( @TargetString, @LastSearchCharPos + 1, DATALENGTH( @TargetString ) ) )
   BREAK
  END
  ELSE
   INSERT @Set( num ) VALUES ( SUBSTRING( @TargetString, @LastSearchCharPos + 1, @SearchCharPos - @LastSearchCharPos - 1 ) )
 END
 RETURN
END

不,数据库有几百万个帐户,我想从数据库中获取的数据包括几个连接,这使得最终结果集更加均匀bigger@Rachel,您是否尝试使用探查器查看正在生成的查询。有一个免费的线索,可以帮助这一点。是的,我有和查询运行良好。从几百万张唱片中提取大约10万张唱片大约需要一秒钟的时间。我觉得不可接受的一点是,EF使用.Contains()在大约10k个项目的列表上生成SQL语句大约需要5分钟。@Rachel,您可以预编译查询,然后它们应该运行得更快。请看一下这个链接。下面是一个如何运行预编译查询的链接。我不确定预编译查询是否会有帮助,因为这不是造成问题的查询,而是
.Contains()
中的10k项列表导致了减速。您可以发布一些代码来显示示例吗?我对linq和实体还是相当陌生的。另外,SQL语句的性能很好(大约需要一秒钟的处理时间),它正在构建花费EF这么长时间的SQL语句。嗯,好的。删除
ToList
就是一个例子。虽然我能理解,但这可能需要一些时间。是否可以以某种方式将
accountIdList
保存在数据库中?然后,您可以使用简单的联接,而不是自动生成的
WHERE IN
子句。
accountIdList
基于用户输入,因此不是。它可以从accountid的excel文件中读取,也可以基于其他用户输入(如销售批次、付款批次等)生成