如何在 EF DbContext 和 AspNet Membership 之间共享连接以避免事务升级到 DTC [英] How to share a connection between EF DbContext and AspNet Membership to avoid transactions escalating to DTC

查看:21
本文介绍了如何在 EF DbContext 和 AspNet Membership 之间共享连接以避免事务升级到 DTC的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have an ASP.NET MVC3 application that uses an EF 4.1 DbContext, database-first data layer. The EDMX approach works fine as I tend to make changes to my data model before adapting the application to them. The application works fine with the special EF connection string that includes metadata references.

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

However, there's one fly in the ointment. The application also uses ASP.NET membership and roles which require a standard connection string. I have several use cases that involve both the membership tables and other (EF managed) tables. As the two use separate connection strings, transactions that involve both need DTS to handle them. I don't want to go that route if I can help it, I'd rather all parts of the application simply use the same connection.

让 EF 使用简单的连接字符串运行但是我无法理解.谁能告诉我它是怎么做的,好吗?

Getting EF to run with a plain connection string however is eluding me. Can anyone tell me how it is done, please?

推荐答案

这里有几个选项.(我知道这很长,但请尝试阅读全文).如果您能给出需要此类交易的实际场景,那将会有所帮助.

You have several options here. (I know this is long, but please try to read the whole thing). It would help if you can give an actual scenario where you need such a transaction.

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

First, you are working on a false assumption that if both EF and Membership have the same connection string, it will use a common connection. This may be true sometimes, but is not guaranteed. Connection pooling tries to use the same connection for a given string, but if a connection is already in use it will create a second connection (or reuse an existing second connection already in the pool). So this line of reasoning will get you in trouble at some point.

Membership 旨在解决的问题之一是拥有一个可插入的提供程序接口,因此您可以更换成员资格提供程序并移动到不同的提供程序(例如从 Sql 转到 ActiveDirectory),而无需修改您的应用程序(或必须对其进行大量修改).

One of the problems that Membership is designed to solve is to have a pluggable provider interface, so you can swap out membership providers and move to a different one (such as going from Sql to ActiveDirectory), without having to modify your application (or having to modify it much).

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

More tightly integrating these functions means throwing that benefit away. Maybe that's acceptable, but you should realize that going along these paths essentially tightly couples your data model to the specific Membership provider schemas. A few years ago, that didn't seem like it would be a problem as the membership system hadn't changed in years... but lately, MS and others have been introducing new Membership systems like SimpleMembership and Universal Providers which have different schemas.

那么,如果我们要删除 Membership 的主要功能之一,为什么还要继续使用它呢?那么,会员资格仍然有一些好处.主要是它提供了用户管理库的开箱即用的完整实现,包括安全密码加密/散列和问答身份验证等功能.这不是小事,因为从头开始创建一个安全、无错误的会员系统并非易事(尽管乍一看似乎如此).

So, if we're removing one of the primary features of Membership, why even continue to use it? Well, there are still some benefits from Membership. The primary one being that it provides an out of box full implementation of a user management library, including secure password encryption/hashing and features like question and answer authentication. That's not something to sneeze at, as doing a secure, bug-free membership system from scratch is not trivial (even though it would seem so at first).

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

So, one option is to implement your own MembershipProvider based on an existing one (like SqlMembershipProvider. Microsoft provides the source for these). Then you can simply override the schema to match whatever you want, but keep all the other features like password encryption and what not. Just fit them into your own schema. That makes them fit your data model a lot better.

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

However, even if you choose to use the standard membership provider, then there are some things you can do.

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

First, you can simply map the membership tables into your Entity Framework model. Just drag and drop them onto your designer, or add them in Code First. However, if you do this, you should only use them as read-only, and you should not create foreign key relationships between the membership tables and your tables. Instead, just do manual joins in your EF query (which is more work, but safer) and treat them as stand-alone tables.

好的,那么在需要更新或删除成员资格表中的数据作为查询的一部分的情况下呢?坦率地说,如果您使用标准成员资格表,我认为几乎没有任何理由必须发生这种情况.

Ok, so what about situations where you need to update or delete data from the membership tables as part of a query? Frankly, if you're using the standard membership tables I see almost no reasons this should ever have to happen.

Membership 表非常简单,其中包含非常少的实际数据,您在应用中的任何语句中都应该需要这些数据.除非您使用的是 Profile 提供程序,我从不这样做.如果您需要映射成员资格表,我建议您创建自己的数据表,而不是使用 ProfileProvider.

The Membership tables are pretty simple and have very little actual data in them you should need as part of any statements in your app. Unless you're using the Profile provider, which I never do. If you need to map the membership tables, I suggest creating your own table of data rather than using the ProfileProvider.

我看到您可能希望在何处登记交易的唯一原因是在创建新用户时.不过,既然这是一次性事件,那么一个DT可能就不是那么可怕的事情了.但是,您可能并不总是可以使用 DTC……因此在这些情况下,您能做的最好的事情就是使用 try-catch 块来处理异常.

The only reason I see where you may want to enlist a transaction is when creating a new user. However, since this is a one-time event, then a DT may not be such a terrible thing. However, there may not always be a DTC available to you... so in those cases, the best you can do is use a try-catch block to deal with exceptions.

另一种方法是完全放弃 Membership 并创建您自己的 IPrincipal 和 IIdentity 实现并简单地编写您自己的用户管理(我仍然会使用 SqlManagementProvider 源作为此的基础,但是,因为它是一个很好的实现).

The alternative is to completely throw away Membership and create your own IPrincipal and IIdentity implementations and simply write your own user management (I would still use the SqlManagementProvider source as a basis for this, however, as it's a good implementation).

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

Then, since user management is not part of a separate subsystem, you can safely use it for updates and deletes without worrying about what the other subsystem might be doing.

TL;博士

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

If you can't accept a DT, then either change your workflows, change your code to work with a try-catch-finally statement (though this won't guarantee rollback in case the app code dies suddenly, like a power outage), or use a custom IPrincipal and IIdentity implementation.

这篇关于如何在 EF DbContext 和 AspNet Membership 之间共享连接以避免事务升级到 DTC的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆