这个问题有三个部分:
可以从here
下载代码假设DataLayer(DAL)由WCF服务实现,并且客户端代码包含从Main调用其操作:
public void Main(string[] args)
{
var dal = new DataLayerServiceClient();
var accounts = dal.GetAccounts();
int accountId = accounts.First().AccountId;
for (int i = 0; i < 10000; i++)
{
using (TransactionScope scope = new TransactionScope())
{
var account = dal.GetAccountById(accountId);
account.Balance++;
dal.Update(account);
scope.Complete();
}
}
}
也假设:
同时运行两个客户端进程。
预期结果是两个客户端退出后的帐户余额应比两个客户端启动前的余额大20000。
两个客户端退出后的帐户余额是10000到20000之间的值。在某些情况下,由于以下错误,其中一个客户端被中止:
事务(进程ID)在锁定资源上与另一个进行了死锁 过程并被选为死锁受害者
每个客户端上TransactionScope范围内包含的操作不会与其他客户端的系列整体运行。 两个事务的读取和写入都是混合的,一些增量丢失了。
答案 0 :(得分:0)
问题:“如果我对隔离的解释不正确,那么正确的解释是什么?”。
答案:问题中的错误假设是,如果两个事务无法同时运行,则会等待另一个事务完成然后继续。这是不正确的。事实上,Serializable事务是孤立的,不会同时运行,但这并不意味着一个人会等待另一个。事务的隔离与持有互斥锁以便单独执行一组操作不同
问题:“我怎样才能修改测试以证明使用序列化交易与完全不使用交易相反的区别”
回答:以下代码段将演示如何使用事务来确保按预期进行增量。
int i = 0;
while(i < 10000)
{
try
{
using (TransactionScope scope = new TransactionScope())
{
var account = dal.GetAccountById(accountId);
account.Balance++;
dal.Update(account);
scope.Complete();
}
i++;
}
catch (Exception ex)
{
Console.WriteLine($"{ex.Message} : restarting");
}
}
当然这是非常低效的,但它按预期工作,并演示了事务如何隔离资源管理器上的操作。