如何在linq-sql中实现数据库记录的互斥

本文关键字:记录 数据库 实现 linq-sql | 更新日期: 2023-09-27 18:26:19

我有一个分布式客户机-服务器系统,它有多个"worker"引擎和一个WCF服务,让我们称之为FileManagerService,它将"jobs"添加到数据库中,供"worker"引擎拾取和处理。

数据库由两个表组成:JobsFile。每个作业都在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-sql中实现数据库记录的互斥

"未更改或未找到行"错误可能很简单,就像数据库模型文件与实际物理数据库模式不匹配一样。

另一个原因可能是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是否是问题所在。