具有两种连接方法的事务范围
我的 ASP.NET MVC 应用程序正在使用应用程序服务作为成员资格。由于多种原因,我没有使用应用程序服务配置文件。我正在管理一堆连接到会员资格表的定制表中的个人资料。 我的域模型由使用实体框架 (DbContext) 映射到我的表(包括配置文件表,但不包括应用程序服务表)的类组成。
当会员资格提供者创建新用户时,我想在我的个人资料表中执行一系列操作,并在任何个人资料准备步骤失败时回滚会员资格创建。
因此,我更改了注册方法,以包含对执行我想要的工作的方法的调用,并将其全部放在 TransactionScope 中。当没有 Transaction 时,代码工作正常,但使用 TransactionScope,一旦从 Repository 类(位于单独的程序集中)调用 context.SaveChanges() 方法,我就会收到错误:“提供程序做了不返回 ProviderManifestToken 字符串。”
using (TransactionScope scope = new TransactionScope())
{
System.Web.Security.MembershipUser newUser = Membership.CreateUser
(model.UserName, model.Password, model.Email, null, null, true, null, out createStatus);
if (createStatus == MembershipCreateStatus.Success)
{
FormsAuthentication.SetAuthCookie(model.UserName, false /* createPersistentCookie */);
// Create the profile and permissions
bool profileCreation = repository.NewUser(newUser.UserName, newUser.ProviderUserKey);
if (profileCreation)
{
scope.Complete();
return RedirectToAction("List", "Project");
}
else scope.Dispose();
}
else
{
scope.Dispose();
ModelState.AddModelError("", ErrorCodeToString(createStatus));
}
}
事务是否可以处理来自实体框架和应用程序服务代码的数据库连接(我不知道它使用什么连接方法)?如果是这样,我该如何实现这一目标?
我将非常感谢任何帮助, 戴夫
My ASP.NET MVC application is using Application Services for Membership. For a number of reasons I am not using the Application Services Profiles. I am managing profiles in a bunch of bespoke tables that are connected to the Membership tables.
My Domain Model consists of classes that map with Entity Framework (DbContext) to my tables (including profile tables but not the Application Services Tables).
When a new user is created by the membership provider, I want to do a bunch of things in my profile tables and rollback the membership creation if any of my profile preparation steps fails.
So I altered the registration method to include a call to the methods that do the work I want and placed it all in a TransactionScope. The code works fine when there is no Transaction, but using a TransactionScope, as soon as the context.SaveChanges() method is called from within the Repository Class (which is in a separate assembly), I get the error: "The provider did not return a ProviderManifestToken string."
using (TransactionScope scope = new TransactionScope())
{
System.Web.Security.MembershipUser newUser = Membership.CreateUser
(model.UserName, model.Password, model.Email, null, null, true, null, out createStatus);
if (createStatus == MembershipCreateStatus.Success)
{
FormsAuthentication.SetAuthCookie(model.UserName, false /* createPersistentCookie */);
// Create the profile and permissions
bool profileCreation = repository.NewUser(newUser.UserName, newUser.ProviderUserKey);
if (profileCreation)
{
scope.Complete();
return RedirectToAction("List", "Project");
}
else scope.Dispose();
}
else
{
scope.Dispose();
ModelState.AddModelError("", ErrorCodeToString(createStatus));
}
}
Is it possible for transactions to handle connections to the database that are coming from Entity Framework and the Application Services code (I don't know what connection method it uses)? If so, how do I achieve this?
I would be very grateful for any help,
Dave
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
听起来可能 EF 或您的会员提供商未列入交易 (
EnlistTransaction
)。每个参与者的 SQL 连接是否与同一服务器(显然是不同的数据存储)?您可以尝试仅使用成员资格提供程序或仅使用实体框架来执行事务范围,以查看哪一个造成了问题。请参阅有关事务范围的帖子用法。
您也不需要调用
scope.Dispose()
,因为您处于using
语句中。这是隐式为您完成的。It sounds like maybe EF or your Membership Provider is not enlisted in the transaction (
EnlistTransaction
). Are the SQL Connections for each participant to the same server (obviously different data stores)? You could try performing the transaction scope using only the Membership Provider, or only the Entity Framework to see which one is causing the grief.See this post regarding transaction scope usage.
You also don't need to call
scope.Dispose()
since you are in ausing
statement. This is implicitly done for you.谢谢 SilverNinja 的建议。答案其实很简单:
从“服务”窗口打开分布式事务协调器 (MSDTC)。
Thank you SilverNinja for the advice. The answer turned out to be quite simple:
Turn on Distributed Transaction Coordinator (MSDTC) from the Services window.