在我的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;
}
答案 0 :(得分:0)
您是否在未明确定义交易的情况下检查了代码?根据您的代码,我会说您正在尝试阅读已修改但未提交的内容。 您可以做的另一个测试是尝试在代码中添加断点并尝试使用READ UNCOMMITTED获取DocumentRepository。