我有一张Publication
表和一张Receipt
表。当我发布数据时,我会在Publication
表中跟踪它。当我的测试客户端从代理接收到该发布时,我会在Receipt
表中跟踪它。
我的Publication
表格上有一个非规范化ReceiptCount
列,以便于报告。
当我的测试用户收到发布时,执行以下代码:
try
{
using (var context = new PublicationVerifierEntities())
{
using (var transaction = new TransactionScope())
{
if (request.PublicationGuid == Guid.Empty)
{
context.AddToUnknownPublications(new UnknownPublication
{
DateReceived = request.DateReceived,
Publication = request.Publication,
});
}
else
{
// look up the publication by Guid
var publication = context.Publications.FirstOrDefault(m => m.PublicationGuid.Equals(request.PublicationGuid));
if (publication == null)
{
throw new Exception("UpdatePublicationReceipt, provided PublicationGuid not found in database.");
}
else
{
context.AddToUnknownPublications(new UnknownPublication
{
DateReceived = request.DateReceived,
Publication = request.Publication,
});
context.AddToReceipts(new Receipt
{
DateReceived = request.DateReceived,
Publication = publication,
});
publication.ReceiptCount++;
}
}
context.SaveChanges(System.Data.Objects.SaveOptions.None);
transaction.Complete();
context.AcceptAllChanges();
}
}
}
catch (Exception ex)
{
_logger.Error("Unable to update publication record receipt.", ex);
throw;
}
问题是如果Receipt
上的插入失败,Publication.ReceiptCount
永远不会回滚。要删除Receipt
表以对其进行测试,ReceiptCount
列会继续成功更新,尽管会抛出System.Data.UpdateException
。我在SQL事件探查器中看到以下查询执行,但没有关于回滚的信息:
exec sp_executesql N'update [dbo].[Publication]
set [ReceiptCount] = @0
where ([PublicationId] = @1)
',N'@0 int,@1 int',@0=10,@1=3414639
exec sp_executesql N'insert [dbo].[Receipt]([PublicationId], [DateInserted], [DateReceived])
values (@0, null, @1)
select [ReceiptId]
from [dbo].[Receipt]
where @@ROWCOUNT > 0 and [ReceiptId] = scope_identity()',N'@0 int,@1 datetime',@0=3414639,@1='2013-02-21 18:12:47:513'
关于SO的另一个答案让我相信我正在做的一切正确:How to rollback a transaction in Entity Framework,所以......
我在这里缺少什么?
到目前为止,我已经尝试使用围绕创建上下文和SaveChanges()的每个重载的语句来包装TransactionScope。什么都没有区别。
TIA!
答案 0 :(得分:1)
提出我的意见,因为结果证明是答案:
您的观察意味着您没有生成事务(您使用隐式事务per语句)。找出TScope没有采取的原因。尝试将其放在新实体之外。注意,如果TScope没有采取任何警告,则会生成。它只是默默无闻。
你的conn str包含Enlist=false
吗?