У меня есть распределенная система клиент-сервер, в которой есть несколько «рабочих» механизмов и служба 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()
.
Спасибо