Массовая вставка и дублирование записей с LINQ to SQL - PullRequest
0 голосов
/ 26 августа 2010

Есть ли лучший метод обработки массовых вставок (через LINQ), но отбрасывать записи, которые уже могут быть в таблице?Или мне придется либо выполнить массовую вставку в таблицу импорта, затем удалить дубликаты, либо вставить одну запись за раз?


08/26/2010 - EDIT # 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.IQueryable 1[MisterMoney.LARS.ZACH.Model.ACH] Intersect[ACH](System.Linq.IQueryable 1 [MisterMoney.LARS.ZACH.Model.ACH],System.Collections.Generic.IEnumerable 1[MisterMoney.LARS.ZACH.Model.ACH], System.Collections.Generic.IEqualityComparer 1 [MisterMoney.LARS.ZACH.Model.ACH]) ', и этот метод нельзя преобразовать в выражение хранилища.

Есть идеи?И да, это полностью соответствует первоначальному вопросу.:)

Ответы [ 3 ]

1 голос
/ 26 августа 2010

Вы не можете выполнять массовые вставки с LINQ to SQL (я полагаю, что вы имели в виду LINQ to SQL, когда говорили «LINQ»).Однако, исходя из того, что вы описываете, я бы порекомендовал проверить новый оператор MERGE в SQL Server 2008. Вставка, обновление и удаление данных с помощью MERGE

Другой пример здесь.

0 голосов
/ 26 августа 2010

Я рекомендую вам просто написать SQL, чтобы выполнить вставку, я считаю, что это намного быстрее, и вы можете заставить его работать именно так, как вы хотите.Когда я делал что-то похожее на это (просто разовая программа), я просто использовал словарь для хранения уже вставленных идентификаторов, чтобы избежать дублирования.

Я считаю, что LINQ to SQL подходит для одной записи илинебольшой набор, который работает всю жизнь в LINQ to SQL.

Или вы можете попробовать использовать Bulk Insert для SQL Server 2008 .

0 голосов
/ 26 августа 2010

Одна вещь, на которую следует обратить внимание, это если вы ставите в очередь более 2000 или около того записей без вызова SubmitChanges () - TSQL имеет ограничение на количество операторов на выполнение, поэтому вы не можете просто поставить в очередь каждую запись и затем вызвать SubmitChanges (), поскольку это вызовет исключение SqlException, вам необходимо периодически очищать очередь, чтобы избежать этого.

...