Asp.net 如何在EF DbContext和AspNet成员资格之间共享连接,以避免事务升级到DTC

Asp.net 如何在EF DbContext和AspNet成员资格之间共享连接,以避免事务升级到DTC,asp.net,entity-framework,asp.net-membership,database-connection,msdtc,Asp.net,Entity Framework,Asp.net Membership,Database Connection,Msdtc,我有一个ASP.NET MVC3应用程序,它使用EF 4.1 DbContext,即数据库第一数据层。EDMX方法工作得很好,因为我倾向于在使应用程序适应数据模型之前对其进行更改。应用程序可以很好地处理包含元数据引用的特殊EF连接字符串 然而,美中不足。该应用程序还使用ASP.NET成员身份和角色,这些角色需要标准连接字符串。我有几个用例涉及成员表和其他(EF管理的)表。由于两者使用单独的连接字符串,因此涉及两者的事务都需要DTS来处理它们。如果我能帮上忙,我不想走这条路,我宁愿应用程序的所有部

我有一个ASP.NET MVC3应用程序,它使用EF 4.1 DbContext,即数据库第一数据层。EDMX方法工作得很好,因为我倾向于在使应用程序适应数据模型之前对其进行更改。应用程序可以很好地处理包含元数据引用的特殊EF连接字符串

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


然而,让EF运行一个简单的连接字符串却让我不知所措。有人能告诉我是怎么做的吗?

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


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

您应该看看基于EF Codefirst的asp.net通用提供程序。成员模式以POCO类和DBSet的形式公开,因此您应该能够将DBSet包含到公共DBContext类中

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

首先,您的假设是错误的,即如果EF和Membership都具有相同的连接字符串,那么它将使用公共连接。这有时可能是真的,但不能保证。连接池尝试对给定字符串使用相同的连接,但如果一个连接已在使用,它将创建第二个连接(或重用池中已有的第二个连接)。所以这条推理路线在某个时候会给你带来麻烦

成员资格设计要解决的一个问题是有一个可插入的提供程序接口,这样您就可以交换成员资格提供程序并移动到另一个提供程序(例如从Sql到ActiveDirectory),而无需修改您的应用程序(或对其进行大量修改)

更紧密地集成这些功能意味着放弃这些好处。也许这是可以接受的,但您应该认识到,沿着这些路径,您的数据模型与特定的成员资格提供程序模式基本上是紧密耦合的。几年前,这似乎不是一个问题,因为会员制多年来没有改变。。。但最近,MS和其他人引入了新的成员系统,如SimpleMembership和Universal Providers,它们具有不同的模式

那么,如果我们要删除会员资格的一个主要功能,为什么还要继续使用它呢?嗯,会员资格还有一些好处。主要的一点是,它提供了一个现成的用户管理库的完整实现,包括安全的密码加密/哈希和问答验证等功能。这不是一件可以忽视的事情,因为从头开始创建一个安全、无缺陷的会员系统并不是一件小事(即使一开始看起来是这样)

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

但是,即使您选择使用标准成员资格提供程序,也可以做一些事情

首先,您可以简单地将成员表映射到实体框架模型中。只需将它们拖放到设计器中,或者先在代码中添加它们。但是,如果执行此操作,则应仅将其用作只读,并且不应在成员资格表和表之间创建外键关系。相反,只需在EF查询中进行手动连接(这会更费力,但更安全),并将其作为独立表处理

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

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

我看到您希望登记事务的唯一原因是创建新用户时。然而,由于这是一次性事件,因此DT可能不是那么可怕的事情。但是,您可能并不总是可以使用DTC。。。因此,在这些情况下,最好使用try-catch块来处理异常

另一种方法是完全抛弃成员身份,创建自己的IPrincipal和IIdentity实现,只编写自己的用户管理(不过,我仍然会使用SqlManagementProvider源代码作为基础,因为这是一个很好的实现)

然后,由于用户管理不是独立子系统的一部分,因此您可以安全地将其用于更新和删除,而不必担心其他子系统可能正在做什么

TL;博士

如果您不能接受DT,则可以更改工作流,更改代码以使用try-catch-finally语句(尽管这不能保证在应用程序代码突然死亡(如断电)时回滚),或者使用自定义的IPrincipal和IIdentity实现。

I discover