C# 如何在linq sql中实现对数据库记录的互斥
我有一个分布式客户机-服务器系统,它有多个“工作者”引擎和一个WCF服务,我们称之为C# 如何在linq sql中实现对数据库记录的互斥,c#,.net,multithreading,linq-to-sql,C#,.net,Multithreading,Linq To Sql,我有一个分布式客户机-服务器系统,它有多个“工作者”引擎和一个WCF服务,我们称之为FileManagerService,它将“作业”添加到数据库中,以便“工作者”引擎拾取和处理 数据库由两个表组成:作业和文件。每个作业都在文件上运行(多对一关系)。可以一次将多个作业添加到作业表中,它们以队列的方式进行处理 作业的示例包括:MoveFile或DeleteFile等操作 我试图通过在文件表本身中使用“锁定”(bool)列,在文件记录上实现互斥 我认为所需的互斥区位于WCF服务FileManager
FileManagerService
,它将“作业”添加到数据库中,以便“工作者”引擎拾取和处理
数据库由两个表组成:作业
和文件
。每个作业都在文件上运行(多对一关系)。可以一次将多个作业添加到作业
表中,它们以队列的方式进行处理
作业
的示例包括:MoveFile或DeleteFile等操作
我试图通过在文件
表本身中使用“锁定”(bool)列,在文件
记录上实现互斥
我认为所需的互斥区位于WCF服务FileManagerService
的方法:addJob()
和“worker”引擎TakeAndProcessAJob()
中
目前,我在解决LINQtoSQL延迟执行以及LINQtoSQL事务系统如何工作方面遇到了困难
我目前有以下方法,应该从作业
表中获取作业
,检查其相关文件
是否已锁定,如果已锁定,我们将不返回任何内容,如果未锁定,我们将锁定文件
并返回作业
,并从作业
队列中删除该作业
:
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()
方法中的SubmitChanges()
上收到更改冲突异常-行未更改或未找到
谢谢,“行未更改或未找到”错误可能很简单,例如数据库模型文件与实际的物理数据库架构不匹配
另一个原因可能是LINQ没有检测到任何要提交的更改。假设您选择的记录已为真,并将其标记为真。您可以通过不更新来避免这种情况,如果它已经为真,或者原因可能是在表上该字段的属性下的模式文件上有一个设置,您可以实际关闭UpdateCheck,但听起来这不是您想要的
在一个无关的故事中:
当找不到与firstOrDefault()相关的内容时,“.Single()”是否会抛出一个错误,firstOrDefault()只返回null?我想不出问题的答案,因此我进行了一些逻辑重组,并使用简单的旧SQL设计了一个解决方案。要锁定记录,我现在对记录使用单行(原子)命令:
updatedatatable SET locked='True'其中(locked='False')和(recordID=15)
然后我使用SqlDataReader
并检查recordsafected
字段。如果记录已更改,则表示我已成功锁定该记录。如果记录未更改,则表示该记录已被锁定,因此我在锁定方法中返回false
试图锁定记录的进程随后位于while循环中,调用lockRecord
并等待成功的回调
我不确定是否完全有必要从LINQ切换到SQL。我在应用程序中进行了逻辑更改,同时切换到计划SQL,因此很难确定使用LINQ是否是问题所在
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;
}
}
}