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

时间:2015-06-24 23:00:50

标签: c# sql-server database-deadlocks

在我的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; 
 }

1 个答案:

答案 0 :(得分:0)

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