LinqToSql. Тупик при обновлении строки. Параллельный.

У меня проблема. Я пытаюсь обновить базу данных с помощью параллельного интерфейса. Вот код:

Parallel.For(rCnt, range.Rows.Count + 1, (jrCnt, loopState) =>
{
    var prcI = new Price(); // new 

    /*bla bla bla bla - bla bla - bla bla - bla */

    if ((!string.IsNullOrEmpty(prcI.name)) && (prcI.prc != 0)) // process add or update
    {
        prcI.company = nameprice;
        prcI.date = datatimeselect.Text; 

        Accessor.AddProductUpdateProduct(prcI); // main func

            /*bla bla bla bla - bla bla - bla bla - bla bla - bla  */
    }

Вот поле кода функции, которое нужно обновить:

public static bool AddProductUpdateProduct(Price price)
    {
        bool add = false;
        var db = new PriceDataContext();

        var matchedprod =
           db.Price.Single(x => x.name == price.name && x.date != price.date && x.company == price.company); // find match

        if (matchedprod != null) // match FOUnDE
        {
            if (matchedprod.prc != price.prc)
            {
                matchedprod.date = price.date;
                matchedprod.prc = price.prc;
            }
            else
            {
                matchedprod.date = price.date;
            }
            db.SubmitChanges(); // DEADLOCK is her!!!
        }
        /*bla - bla bla - bla bla - bla bla - bla bla - bla */
    }

Когда я создаю запись, все хорошо!

Спасибо!


person JinDeveloper    schedule 26.12.2011    source источник
comment
Сколько записей вы здесь обновляете / вставляете?   -  person Marc Gravell    schedule 26.12.2011
comment
иначе от 3000 до 10000.   -  person JinDeveloper    schedule 26.12.2011


Ответы (2)


При количестве записей от 3000 до 10000 (комментарии) я бы посмотрел на решение здесь, которое использовало бы SqlBulkCopy для вставки данных в промежуточную таблицу (т.е. таблицу, которая похожа на данные, которыми вы манипулируете, но не является частью вашего ядра). модель). Это наиболее эффективный способ доставки большого количества данных на сервер (хотя вы также можете посмотреть на параметры, оцениваемые по таблице).

Затем с данными на сервере я бы сделал либо одно обновление (внутреннее соединение) и одну вставку (если не существует), либо одно «upsert» (доступно в SQL Server 2008 и выше).

Это использует меньше ЦП на сервере приложений, меньше сети и меньше ресурсов базы данных. Кроме того, поскольку во вставке / обновлении задействован только один SPID, риск тупиковой ситуации отсутствует.

person Marc Gravell    schedule 26.12.2011
comment
Теперь попробуйте использовать SqlBulkCopy. И данные лучше хранить в datatable, а затем выгружать? - person JinDeveloper; 26.12.2011
comment
@Jin ты можешь перефразировать? Я не совсем понимаю ваш комментарий. Но да: DataTable - это один из способов передать данные в экземпляр SqlBulkCopy. Но перед этим это не обязательно должно быть в DataTable. - person Marc Gravell; 26.12.2011
comment
Я читал о SqlBulkCopy. Это только добавляет в базу? По поводу обновления информации не нашел. - person JinDeveloper; 26.12.2011
comment
@Jin да, поэтому вы вставляете в STAGING таблицу (как я уже упоминал), а затем затем выполняете вставку / обновление в основные таблицы. - person Marc Gravell; 26.12.2011
comment
Ну у меня не все данные взяты из одного места. У меня есть еще один столбец со строкой данных, которые добавляются к другой функции. Извините за недопонимание. Я русский, и мой английский, который я знаю, идеален. Если бы вы могли привести пример. Я очень благодарен за вашу помощь. - person JinDeveloper; 26.12.2011
comment
@Jin твой английский лучше моего русского! Вы должны иметь возможность создать DataTable со всеми необходимыми столбцами ..? - person Marc Gravell; 26.12.2011

Я предполагаю, что это может быть та же проблема, которую я описал в этом вопросе Тупик при SELECT / UPDATE. Это не проблема linq to sql. Проблема с linq to sql заключается в том, что вы не можете легко выполнить выбор с помощью Updlock.

person empi    schedule 26.12.2011
comment
Да, но без уровня изоляции первый выбор должен быть изолирован и снять любые блокировки чтения после выбора; кроме того, без Serializable это не должно быть блокировки диапазона клавиш. Не совсем тот же сценарий, ИМО - person Marc Gravell; 26.12.2011
comment
Не понимаю как реализовать. Я с этой проблемой уже неделю борюсь. Скажи мне, пожалуйста. - person JinDeveloper; 26.12.2011
comment
Это нужно делать параллельно? Проблема возникает из-за того, что несколько потоков работают с данными в одной таблице. Самый простой обходной путь - выполнение операции в одном потоке. В противном случае я бы написал хранимую процедуру, которая будет использовать select with updlock, а затем добавлять или обновлять. - person empi; 26.12.2011