如何在linq-sql中实现数据库记录的互斥
本文关键字:记录 数据库 实现 linq-sql | 更新日期: 2023-09-27 18:26:19
我有一个分布式客户机-服务器系统,它有多个"worker"引擎和一个WCF服务,让我们称之为FileManagerService
,它将"jobs"添加到数据库中,供"worker"引擎拾取和处理。
数据库由两个表组成:Jobs
和File
。每个作业都在File
(多对一关系)上运行。多个作业可以同时添加到Jobs
表中,它们以队列的方式进行处理。
Job
的示例是诸如MoveFile或DeleteFile等操作。
我试图通过在File
表中使用"locked"(bool)列来实现File
记录的互斥。
我认为需要的互斥区在WCF服务FileManagerService
的方法addJob()
和"工作引擎"TakeAndProcessAJob()
中。
目前,我很难弄清楚linq-to-sql延迟执行的方式以及linq-to-sql事务系统的工作方式。
我目前有以下方法,该方法应该从Jobs
表中获取一个Job
,检查其相关的File
是否已锁定,如果已锁定,我们将不返回任何内容,如果未锁定,我们会锁定File
并返回Job
,并从Jobs
队列中删除该Job
:
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;
}
}
"worker"引擎TakeAndProcessAJob()
基本上执行以下操作:如果返回对象不为null,则调用GetAnAvailableJob()
->处理作业,如果为null->休眠。
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
记录上具有互斥性。目前,我在TakeAndProcessAJob()
方法中的SubmitChanges()
上得到了更改冲突异常——行未更改或未找到。
感谢
"未更改或未找到行"错误可能很简单,就像数据库模型文件与实际物理数据库模式不匹配一样。
另一个原因可能是LINQ没有检测到要提交的任何更改。假设您选择的记录已经为真,并将其标记为真。如果这已经是真的,或者可能是因为在表上该字段的属性下的模态文件上有一个设置,你实际上可以关闭UpdateCheck,但听起来并不是你想要的,那么你可以通过不更新来避免这种情况。
在一个无关的故事中:当没有找到任何作为第一个或默认值()的aposed的值时,".Single()"不会抛出错误吗?
我找不出问题的答案,所以我进行了一些逻辑重组,并使用普通的旧SQL设计了一个解决方法。为了锁定记录,我现在在记录上使用单行(原子)命令:
UPDATE dataTable SET locked = 'True' WHERE (locked = 'False') AND (recordID= 15)
然后我使用SqlDataReader
并检查RecordsAffected
字段。如果记录已更改,则表示我已成功锁定该记录。如果记录没有更改,则表示该记录已被锁定,因此我在锁定方法上返回false
。
然后,试图锁定记录的进程处于while循环中,调用lockRecord
并等待成功的回调。
我不确定是否完全有必要从LINQ切换到SQL。我在应用程序中进行了逻辑更改,同时切换到计划SQL,因此很难确定使用LINQ是否是问题所在。