Как добиться взаимного исключения из записи базы данных в linq sql - PullRequest
0 голосов
/ 02 марта 2012

У меня есть распределенная система клиент-сервер, в которой есть несколько «рабочих» механизмов и служба WCF. Давайте назовем ее «1001», которая добавляет «задания» в базу данных для «рабочих» механизмов, которые нужно собирать и обрабатывать.

База данных состоит из двух таблиц: Jobs и File. Каждая работа работает по принципу File (отношения многие к одному). В таблицу Jobs можно добавить несколько заданий одновременно, они обрабатываются в виде очереди.

Примером Job являются такие действия, как: MoveFile или DeleteFile и т. Д.

Я пытаюсь добиться взаимного исключения в записи File с помощью столбца «заблокирован» (bool) в самой таблице File.

Зоны взаимного исключения, которые, на мой взгляд, необходимы, находятся в методе WCF FileManagerService: addJob() и в "рабочих" механизмах TakeAndProcessAJob().

В настоящее время у меня возникают проблемы с выяснением того, как отложенное выполнение linq-to-sql и как работает система транзакций linq-to-sql.

В настоящее время у меня есть следующий метод, который должен взять Job из таблицы Jobs, проверить, заблокирован ли связанный с ним File, если он заблокирован, мы ничего не вернем, если он не заблокирован, мы заблокирует File, вернет Job и удалит Job из очереди Jobs:

public static Job GetAnAvailableJob()
{
    using (DBDataContext db = new DBDataContext())
    {
        DataLoadOptions loadOptions = new DataLoadOptions();
        loadOptions.LoadWith<Job>(f => f.File);
        db.LoadOptions = loadOptions;
        var jobAvailable = from ja in db.Jobs
                                    where ja.File.locked == false
                                    select ja;
        var jobToTake = jobAvailable.FirstOrDefault();
        // This file temp is here so that we can return
        // an associated File with the Job.
        // We delete
        File fileTemp = null;
        if (jobToTake != null)
        {
            fileTemp = jobToTake.File;
            jobAvailable.File.locked = true;
            Console.WriteLine("Locked file:" + fileTemp.FileID);
            db.Jobs.DeleteOnSubmit(jobToTake);
            db.SubmitChanges();
            jobToTake.Asset = fileTemp;
        }
        return jobToTake;
    }
}

Механизмы 'работника' TakeAndProcessAJob() в основном делают следующее: Вызовите GetAnAvailableJob(), если возвращаемый объект не равен NULL -> обработать задание, если он имеет значение NULL -> Sleep.

Служба WCF FileManagerService использует этот метод блокировки:

public static bool LockAsset(long FileID)
{
    using (DBDataContext db = new DBDataContext())
    {
        var fileToLock = db.Files.Where(f => f.FileID == FileID && f.locked == false).Single();
        if (fileToLock == null)
        {
            return false;
        }
        else
        {
            Console.WriteLine("Locked File:" + fileToLock.AssetID);
            fileToLock.locked = true;
            db.SubmitChanges();
            return true;
        }
    }
}

Что мне нужно изменить в этих двух методах, чтобы потом вести себя транзакционно и иметь взаимное исключение в записи File. В настоящее время я получаю исключения конфликта изменений - строка не изменена или не найдена - в SubmitChanges() в методе TakeAndProcessAJob().

Спасибо

Ответы [ 2 ]

0 голосов
/ 09 марта 2012

Я не мог найти ответ на свой вопрос, поэтому я провел некоторую логическую реструктуризацию и разработал обходной путь, используя простой старый SQL.Чтобы заблокировать запись, я теперь использую однострочную (атомарную) команду для записи:

UPDATE dataTable SET locked = 'True' WHERE (locked = 'False') AND (recordID= 15)

Затем я использую SqlDataReader и проверяю поле RecordsAffected.Если записи изменились, значит, я успешно заблокировал запись.Если записи не изменились, это означает, что запись уже заблокирована, и поэтому я возвращаю false в моем методе блокировки.

Процесс, который пытается заблокировать запись, затем находится в цикле while, вызывающем lockRecord и в ожидании успешного обратного вызова.

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

0 голосов
/ 08 марта 2012

Эта ошибка "строка не изменена или найдена" может быть такой же простой, как файл модели базы данных, не соответствующий фактической физической схеме базы данных.

Другая причина может заключаться в том, что LINQ не обнаружил никаких изменений для отправки.,Скажите, что выбранная вами запись уже была истинной, и вы отметили ее как истинную.Вы можете избежать этого, не обновляя, если это уже верно или, возможно, причина в том, что в модальном файле под свойствами этого поля таблицы есть параметр, который вы можете фактически отключить UpdateCheck, но это не похоже на то, что выwant.

В несвязанной истории: не ".Single ()" выдает ошибку, когда ничего не найдено, как применительно к firstOrDefault (), который просто возвращает ноль?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...