为什么我的代码被多次访问时会出现死锁

本文关键字:死锁 访问 我的 代码 为什么 | 更新日期: 2023-09-27 17:59:47

在我的c#代码中,我有以下方法在数据库中创建一个文档,将有关文档的元数据添加到数据库中,然后更新有关存储库上次更新日期的一些信息。由于多个文件上传很常见,因此这种方法经常被快速连续调用多次。然而,由于sql server中的死锁,我遇到了代码失败的问题。

private IEnumerable<DocumentMetadata> CreateDoc(int? jobId, int?repositoryId, int? folderId, string documentTypeString,       IEnumerable<DocumentModel> files)
{
    if ((jobId == null && repositoryId == null) || (jobId != null && repositoryId != null))
        {
            throw new InvalidOperationException("Either job id or repository id must be specified");
        }
    using (var tran = new TransactionScope())
    {
        List<DocumentMetadata> newDocuments = new List<DocumentMetadata>();
        var documentType = GetDocumentTypeByPrefix(documentTypeString);
        if (folderId == null)
        {
            // Find the root folder
            var job = getJob(jobId);
            var rootFolder = getRootFolder(job);
            // If we can't find a root folder, create one
            if (rootFolder == null)
            {
                rootFolder = CreateRootDirectory(job);
            }
            folderId = rootFolder.FolderId;
        }
        User currentUser = _userService.GetCurrentUser();
        foreach (var file in files)
        {
            var document = new Document() { Document1 = file.Data };
            var documentMetadata = new DocumentMetadata
            {
                Document = document,
                CreatedDate = file.CreatedDate,
                FileName = file.Filename,
                FileSize = file.Data.Length,
                FolderId = folderId,
                DocumentType = documentType,
                JobId = jobId,
                RepositoryId = repositoryId,
                User = currentUser
            };
            _unitOfWork.DocumentMetadata.Add(documentMetadata);
            newDocuments.Add(documentMetadata);
        }
        // set repository updated date 
        if (repositoryId != null)
        {
            DocumentRepository repo = GetDocumentRepository(repositoryId);
            if (repo != null)
            {
                repo.UpdatedDate = new DateTimeOffset(DateTime.Now);
            }
        }
        _unitOfWork.SaveChanges();
        tran.Complete();
        return newDocuments;
    }
}

经过一些调试后,存储库id的更新似乎导致了死锁问题。如果我在事务之外删除此代码块,则保存所有文件时不会出现错误。

为什么这个代码会阻止

if (repositoryId != null)
        {
            DocumentRepository repo = GetDocumentRepository(repositoryId);
            if (repo != null)
            {
                repo.UpdatedDate = new DateTimeOffset(DateTime.Now);
            }
        }

造成僵局?除了在这个方法中之外,没有对DocumentRepository表进行其他访问——因为锁是按照相同的顺序获得的——当然不应该有死锁吗?

这段代码是怎么导致死锁的?

更新:GetDocumentRepository的代码为:

 public DocumentRepository GetDocumentRepository(int repositoryId) 
 { 
     var result = DocumentRepositories.SingleOrDefault(x => x.RepositoryId == repositoryId); return result; 
 }

为什么我的代码被多次访问时会出现死锁

您是否在没有明确定义事务的情况下检查了代码?根据你的代码,我想说你正在尝试阅读一些经过修改但未提交的内容。您可以做的另一个测试是尝试在代码中添加断点,并尝试使用READ UNCOMITTED获取DocumentRepository。