我想知道实施以下内容的最佳方式或做法是什么:
我有一个名为EditUser的方法,其定义如下:
public void EditUser(user user, Roles role)
{
using (TestEntities entities = new TestEntities())
{
entities.Connection.Open();
using (DbTransaction trans = entities.Connection.BeginTransaction())
{
try
{
var tmpUser = entities.users.Where(fields => fields.UserId == user.UserId).FirstOrDefault();
RoleManagement rm = new RoleManagement();
string oldRole = tmpUser.roles.FirstOrDefault().Name;
string newRole = rm.GetRoleName(role);
if (oldRole == newRole)
{
entities.users.ApplyCurrentValues(user);
}
else
{
rm.UnbindRoles(tmpUser.UserId, entities.Connection);
this.DeleteUser(tmpUser.UserId, entities.Connection);
this.Register(user, role, entities.Connection);
}
entities.SaveChanges();
trans.Commit();
}
catch (Exception ex)
{
trans.Rollback();
throw ex;
}
}
}
}
正如您可能已经注意到我正在调用几种方法:UnbindRoles,DeleteUser和RegisterUser,其中所有这些方法都需要在同一事务下运行(EditUser正在运行相同的事务),万一出现故障,我将需要回滚。 / p>
现在我的问题主要在这里......方法RegisterUser也会启动一个新的事务,因为它添加了一个用户并为新用户分配了一个角色。
有人能描述如何实现这个的最佳方法吗?我尝试使用TransactionScope块,但由于我在中等信任环境中运行此应用程序,因此失败了
修改
确认MySQL .NET连接器提供程序在Medium Trust下使用TransactionScope时有错误,因为我刚刚使用MS SQL Server数据库测试了相同的场景,并且它没有任何问题
答案 0 :(得分:1)
如果我理解正确你遇到的问题是你对DeleteUser和RegisterUser的调用正在开始新的交易,需要登记当前的交易。
解决此问题的几种方法:
A)当你创建一个transactioncope时,你可以说他们只需要创建一个,如果没有一个已经可用。
B)而不是第一种方法引入私有方法,让我们说InnerEdit和InnerRegister包含逻辑,但不打开或关闭代码保留在公共可用的编辑和注册方法中的任何事务。这些“内部”方法可以重复使用,而公共方法包含基础结构。如果您正在使用第二种方法谷歌进行面向方面编程,那可以解决这些“交叉问题”
public void EditUser(user user, Roles role)
{
using (TestEntities entities = new TestEntities())
{
entities.Connection.Open();
using (DbTransaction trans = entities.Connection.BeginTransaction())
{
InnerEditUser(entities, trans);
InnerThat(entities, trans);
InnerThis(entities,trans);
entities.SaveChanges();
trans.Commit();
}
}
}
答案 1 :(得分:0)
您是否可以注册检查现有交易,如果不存在则只创建一个?这就是嵌套的TransactionScopes在类似情况下会做的事情。