使用 LINQ to SQL 批量插入和复制记录

Posted

技术标签:

【中文标题】使用 LINQ to SQL 批量插入和复制记录【英文标题】:Bulk inserts and duplicate records with LINQ to SQL 【发布时间】:2011-04-04 01:32:26 【问题描述】:

是否存在处理批量插入(通过 LINQ)但丢弃可能已经在表中的记录的“最佳实践”方式?或者我将不得不对导入表进行批量插入然后删除重复项,或者一次插入一条记录?


2010 年 8 月 26 日 - 编辑 #1: 我现在正在研究 Intersect 和 except 方法。我正在从不同的来源收集数据,转换成一个列表,想要与目标数据库“比较”,然后只插入新记录。

List<DTO.GatherACH> allACHes = new List<DTO.GatherACH>();
State.IState myState = null;
State.Factory factory = State.Factory.Instance;
foreach (DTO.Rule rule in Helpers.Config.Rules)

    myState = factory.CreateState(rule.StateName);
    List<DTO.GatherACH> stateACHes = myState.GatherACH();
    allACHes.AddRange(stateACHes);


List<Model.ACH> newRecords = new List<Model.ACH>();  // Create a disconnected "record set"...
foreach (DTO.GatherACH record in allACHes)

        var storeInfo = dbZach.StoreInfoes.Where(a => a.StoreCode == record.StoreCode && (a.TypeID == 2 || a.TypeID == 4)).FirstOrDefault();

        Model.ACH insertACH = new Model.ACH
        
            StoreInfoID = storeInfo.ID,
            SourceDatabaseID = (byte)sourceDB.ID,
            LoanID = (long)record.LoanID,
            PaymentID = (long)record.PaymentID,
            LastName = record.LastName,
            FirstName = record.FirstName,
            MICR = record.MICR,
            Amount = (decimal)record.Amount,
            CheckDate = record.CheckDate
        ;
        newRecords.Add(insertACH);

上面的代码构建了 newRecords 列表。现在,我试图通过比较 3 字段唯一索引来从此列表中获取不在数据库中的记录:

AchExceptComparer myComparer = new AchExceptComparer();
var validRecords = dbZach.ACHes.Intersect(newRecords, myComparer).ToList();

比较器看起来像:

class AchExceptComparer : IEqualityComparer<Model.ACH>

    public bool Equals(Model.ACH x, Model.ACH y)
    
        return (x.LoanID == y.LoanID && x.PaymentID == y.PaymentID && x.SourceDatabaseID == y.SourceDatabaseID);
    

    public int GetHashCode(Model.ACH obj)
    
        return base.GetHashCode();
    

但是,我收到此错误:

LINQ to Entities 无法识别方法 'System.Linq.IQueryable1[MisterMoney.LARS.ZACH.Model.ACH] Intersect[ACH](System.Linq.IQueryable1[MisterMoney.LARS.ZACH.Model.ACH]、System.Collections.Generic.IEnumerable1[MisterMoney.LARS.ZACH.Model.ACH], System.Collections.Generic.IEqualityComparer1[MisterMoney.LARS.ZACH] .Model.ACH])' 方法,并且该方法不能翻译成商店表达式。

有什么想法吗?是的,这完全符合原始问题。 :)

【问题讨论】:

是的 - 你是对的。我用 C# 而不是 VB 编写,并且通常有我的问题的代码示例。对不起。 【参考方案1】:

您不能使用 LINQ to SQL 进行批量插入(我假设您在说“LINQ”时指的是 LINQ to SQL)。但是,根据您的描述,我建议您查看 SQL Server 2008 的新 MERGE 运算符。 Inserting, Updating, and Deleting Data by Using MERGE

Another example here.

【讨论】:

谢谢。不幸的是,这不是我需要去的方向。对于直接导入场景,我很乐意使用它。我扩充了我最初的问题,以帮助(希望)明确我正在尝试做的事情。【参考方案2】:

我建议你自己编写 SQL 来进行插入,我发现它要快得多,而且你可以让它完全按照你想要的方式工作。当我做了类似的事情(只是一个一次性程序)时,我只是使用字典来保存我已经插入的 ID,以避免重复。

我发现 LINQ to SQL 适用于在 LINQ to SQL 中完成其整个生命周期的一条记录或一小组记录。

或者你可以尝试使用SQL Server 2008's Bulk Insert。

【讨论】:

【参考方案3】:

需要注意的一件事是,如果您在不调用 SubmitChanges() 的情况下排队超过 2000 条左右的记录 - TSQL 对每次执行的语句数有限制,因此您不能简单地将每条记录排队然后调用 SubmitChanges( ) 因为这会抛出 SqlException,您需要定期清除队列以避免这种情况。

【讨论】:

很高兴知道。我最大的进口客户现在有 459 条记录(在他们的提要中)。当我削减它时,我平均每天 5 次插入、10 次更新和 5 次删除。其余的没有改变,所以我不需要对它们执行任何操作。

以上是关于使用 LINQ to SQL 批量插入和复制记录的主要内容,如果未能解决你的问题,请参考以下文章

Linq To SQL和Linq To Object的批量操作InsertAllOnSubmit介绍

IDENTITY INSERT 和 LINQ to SQL

如何删除 Linq to Entity 中的多条记录? [复制]

在 Windows Phone 上使用 Linq to SQL 时,是不是可以提高批量删除的性能?

Linq-To-Sql 尝试插入父实体而不是子实体

LINQ to SQL(基于3个表插入事实表)