C# 在LINQ to实体中检查重复项的最快方法是什么?

C# 在LINQ to实体中检查重复项的最快方法是什么?,c#,entity-framework,linq-to-entities,azure-sql-database,C#,Entity Framework,Linq To Entities,Azure Sql Database,我有一个在SQLAzure表中存储字符串的表。用户可以从web浏览器上载新字符串的文件,我正在根据实体框架上下文检查重复的字符串。将消除重复的字符串添加到上下文的代码如下所示: using (StreamReader sr = new StreamReader(theStream)) { string line; while ((line = sr.ReadLine()) != null) { if (!context.MyEntity.Any(o =&g

我有一个在SQLAzure表中存储字符串的表。用户可以从web浏览器上载新字符串的文件,我正在根据实体框架上下文检查重复的字符串。将消除重复的字符串添加到上下文的代码如下所示:

using (StreamReader sr = new StreamReader(theStream))
{
    string line;
    while ((line = sr.ReadLine()) != null)
    {
        if (!context.MyEntity.Any(o => o.String == line))
        {
            theString = new DAL.TheString();
            theString .String = line;
            context.MyEntity.Add(theString );
            totalAdded++;
        }
    }
}
使用MyEntity.Any()太慢了。处理20000个字符串需要40分钟,一些简单的编排似乎指向重复检查


我的问题是:在EF中,最快的方法是什么?L2E不是这项工作的最佳工具吗?我应该彻底摆脱EF吗?或者我应该将文件排队并设置后台工作程序,因为这样做的速度总是很慢。

假设您的数据库表不是太大以至于字符串无法全部放入内存,您可以通过一次查询将它们放入
哈希集
,然后根据内存集合中的字符串进行查询:

var lines = new HashSet<string>(context.MyEntity.Select(o => o.Property));
using (StreamReader sr = new StreamReader(theStream))
{
    while (!sr.EndOfStream)
    {
        string line = sr.ReadLine();
        if (lines.Add(line))
        {
            //add line
        }
    }
}
var-lines=newhashset(context.MyEntity.Select(o=>o.Property));
使用(StreamReader sr=新的StreamReader(theStream))
{
而(!sr.EndOfStream)
{
字符串行=sr.ReadLine();
如果(行。添加(行))
{
//添加行
}
}
}

如果您没有足够的内存来执行此操作,那么最好的办法可能是在数据库中创建一个新触发器,以验证属性是否唯一,这将抛出尝试创建重复项的记录。然后,您可以尝试添加流中的所有行,并让DB在获取所有行时确定要保留哪些行。

您是否已连接SQL Profiler以确认正在向DB发送EXISTS()查询?字符串列是否编制索引以支持这些查询?在NHibernate中,有一个由“上下文”维护的对象缓存。如果我在NH中这样做,我要么禁用缓存,要么在添加对象后逐出每个对象。否则,上下文将保留这些20k对象引用,这将真正减慢这样的迭代处理。EF是否有类似的缓存策略?@SethPetry-Johnson它怎么可能不被发送到数据库?当然是。而且,通过使用索引,它的效率如何也无关紧要。即使是最快的DB查询执行20000次也会很昂贵。@Servy-如果谓词不能转换为t-SQL,它可能会收回所有对象,然后在内存中进行测试。不要认为这是问题所在,但只需一秒钟即可确认。索引有很大的不同;在40分钟内查找20k PK是非常可能的。重点是,这些是我确定的第一个故障排除步骤,目的是获取有关问题的更多信息。你有什么建设性的补充吗?@SethPetry-Johnson正如我之前所说的,每次都会ping数据库。这就是EF的建造方式。我不需要测试任何东西就知道了。是的,索引会有帮助,我不是说不会。我是说,这还远远不够。即使索引执行20000个索引查询,也需要很长时间。您需要完全避免执行如此多的查询,而不是提高查询效率。不需要触发器,只需在列上创建一个唯一索引,并在循环中捕获重复键异常即可。@SethPetry-Johnson,这将取决于使用的特定DB类型。我不知道他在用什么数据库,也不知道它是否支持这样的功能,但如果你可以使用的话,一定要使用它。想法是一样的。这很有效,谢谢。现在我在SaveChanges()上绑定了处理器。有更好的问题。