如何在EF DbContext和AspNet Membership之间共享连接,以避免事务升级到DTC

时间:2012-09-13 14:50:27

标签: asp.net entity-framework asp.net-membership database-connection msdtc

我有一个ASP.NET MVC3应用程序,它使用EF 4.1 DbContext,数据库优先数据层。 EDMX方法工作正常,因为我倾向于在将应用程序调整到它之前对我的数据模型进行更改。该应用程序适用于包含元数据引用的特殊EF连接字符串。

然而,美中不足的是。该应用程序还使用需要标准连接字符串的ASP.NET成员资格和角色。我有几个涉及成员资格表和其他(EF托管)表的用例。由于两者使用单独的连接字符串,涉及两者的事务都需要DTS来处理它们。如果我可以帮助它,我不想走那条路,我宁愿应用程序的所有部分只使用相同的连接。

让EF使用普通连接字符串运行但是让我不知所措。有人能告诉我它是怎么做的吗?

4 个答案:

答案 0 :(得分:6)

这里有几个选项。 (我知道这很长,但请尽量阅读整篇文章)。如果你能给出一个你需要这样一个交易的实际场景,那将会有所帮助。

首先,您正在假设如果EF和Membership都具有相同的连接字符串,它将使用公共连接。有时这可能是真的,但不能保证。连接池尝试对给定的字符串使用相同的连接,但是如果连接已在使用中,它将创建第二个连接(或重用池中已有的现有第二个连接)。所以这种推理会让你在某些时候遇到麻烦。

Membership要解决的一个问题是拥有一个可插拔的提供程序接口,因此您可以更换成员资格提供程序并转移到另一个(例如从Sql转到ActiveDirectory),而无需修改您的应用程序(或必须修改它)。

更紧密地整合这些功能意味着将这些功能抛弃。也许这是可以接受的,但是您应该意识到,沿着这些路径将您的数据模型与特定的成员资格提供者模式紧密地结合在一起。几年前,这似乎不是一个问题,因为会员制度多年来没有改变......但最近,MS和其他人一直在推出新的会员制度,如SimpleMembership和Universal Providers,它们有不同的模式

那么,如果我们要删除会员资格的一个主要功能,为什么还要继续使用呢?好吧,会员资格还有一些好处。主要的一点是它提供了用户管理库的开箱即用的完整实现,包括安全密码加密/散列以及问答验证等功能。这不是打喷嚏的事情,因为从头开始做一个安全,无错误的会员系统并不是微不足道的(尽管起初看起来似乎如此)。

因此,一种选择是基于现有的MembershipProvider实现自己的MembershipProvider(如SqlMembershipProvider。Microsoft为这些提供了源代码)。然后,您可以简单地覆盖架构以匹配您想要的任何内容,但保留所有其他功能,如密码加密和其他功能。只需将它们放入您自己的架构中。这使它们更适合您的数据模型。

但是,即使您选择使用标准会员提供商,也可以做一些事情。

首先,您可以简单地将成员资格表映射到您的Entity Framework模型中。只需将它们拖放到设计器上,或将它们添加到Code First中即可。但是,如果执行此操作,则只应将它们用作只读,并且不应在成员资格表和表之间创建外键关系。相反,只需在EF查询中进行手动连接(这是更多工作,但更安全)并将它们视为独立表。

好的,那么您需要在成员资格表中更新或删除数据作为查询的一部分呢?坦率地说,如果您使用的是标准会员表,我几乎看不出应该发生这种情况的原因。

会员表非常简单,其中包含的实际数据非常少,您应该将其作为应用中任何语句的一部分。除非您使用的是配置文件提供程序,否则我从不这样做。如果您需要映射成员资格表,我建议您创建自己的数据表,而不是使用ProfileProvider。

我看到您可能想要获取交易的唯一原因是创建新用户时。但是,由于这是一次性事件,因此DT可能不是那么可怕的事情。但是,可能并不总是有可用的DTC ...因此在这些情况下,您可以做的最好的事情是使用try-catch块来处理异常。

另一种方法是完全抛弃Membership并创建自己的IPrincipal和IIdentity实现,只需编写自己的用户管理(我仍然会使用SqlManagementProvider源作为基础,但是,因为它是一个很好的实现)。 / p>

然后,由于用户管理不是单独子系统的一部分,因此您可以安全地将其用于更新和删除,而无需担心其他子系统可能正在执行的操作。

TL; DR

如果你不能接受DT,那么要么改变你的工作流程,要改变你的代码以使用try-catch-finally语句(尽管这不能保证在应用代码突然死亡的情况下回滚,就像电源一样中断),或使用自定义IPrincipal和IIdentity实现。

答案 1 :(得分:2)

我在这里找到了答案:https://stackoverflow.com/a/3408209/1169670。将“Enlist = false”添加到ASP.NET成员身份系统的连接字符串会停止升级到DTC。

但是,这种方法只会阻止会员系统在交易中登记。这对我的要求来说已经足够了,但可能并非在每种情况下都适用。

答案 2 :(得分:1)

您应该查看基于EF Codefirst的asp.net通用提供程序。成员模式作为POCO类和DBSet公开,因此您应该能够将DBSet包含到公共DBContext类中 http://nuget.org/packages/Microsoft.AspNet.providers.core

答案 3 :(得分:0)

我认为你不能让EF使用“普通”连接字符串。

在一些应用程序中,我有相同的普通和EF连接字符串并排坐着