ADO.NET 实体框架的 ASP.NET Providers






4.90/5 (25投票s)
ADO.NET 实体框架的引入隐含地创建了对 ASP.NET providers(例如 membership、role 和 profile)的需求,这些 providers 利用了这项新技术。
引言
ASP.NET 2.0 最强大的改进之一是 membership、role 和 profile providers 的引入。 它们允许将用户管理、基于角色的安全性以及基于访问者的页面自定义快速集成到您的 ASP.NET 应用程序中。 名称已经表明它们都实现了 provider model 设计模式。
遗憾的是,Microsoft 没有准备好下载利用 ADO.NET 实体框架的这些 providers。
本文的可下载源代码为上述 providers 提供了即用型实现。 以下文章简要概述了 providers,并描述了如何启动和运行提供的源代码。
为了理解源代码,LINQ 的扎实知识是不可避免的。 此外,重要的是读者要理解 ASP.NET providers 背后的理念。以下链接给出了 ASP.NET providers 的一个很好的概述。
背景
Provider Model 设计模式
provider model 模式旨在提供一个可配置的组件,用于数据访问,该组件是从 *web.config* 定义的。 Provider 在业务逻辑和数据访问之间建立接口。 provider 的实际具体实现在 *web.config* 中定义。 无需更改应用程序设计,即可在 *web.config* 中构建和配置自定义 providers。 Providers 是 `ProviderBase` 类的子类,通常使用工厂方法实例化。
用于相同目的的各种 providers 可以共存,并且可以轻松地在 *web.config* 中配置。
数据库架构
数据库架构与 *aspnet_regsql.exe* 创建的架构密切相关
生成的实体模型如下所示
与 Microsoft 的 SQL ASP.NET providers 不同,这里提出的解决方案不使用存储过程。 相反,所有查询都是使用 LINQ 在各自 providers 的源代码中实现的。
公开的 API
成员资格提供程序
void Initialize(string name, NameValueCollection config)
MembershipUser CreateUser(string username, string password, string email,
string passwordQuestion, string passwordAnswer,
bool isApproved,object providerUserKey,
out MembershipCreateStatus status)
bool ChangePasswordQuestionAndAnswer(string username, string password,
string newPasswordQuestion, string newPasswordAnswer)
string GetPassword(string username, string answer)
bool ChangePassword(string username, string oldPassword, string newPassword)
string ResetPassword(string username, string answer)
void UpdateUser(MembershipUser membershipUser)
bool ValidateUser(string username, string password)
bool UnlockUser(string username)
MembershipUser GetUser(object providerUserKey, bool userIsOnline)
string GetUserNameByEmail(string email)
bool DeleteUser(string username, bool deleteAllRelatedData)
MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
int GetNumberOfUsersOnline()
MembershipUserCollection FindUsersByName
(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
MembershipUserCollection FindUsersByEmail
(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
Role Provider
void Initialize(string name, NameValueCollection config)
bool IsUserInRole(string username, string roleName)
string[] GetRolesForUser(string username)
void CreateRole(string roleName)
bool DeleteRole(string roleName, bool throwOnPopulatedRole)
bool RoleExists(string roleName)
void AddUsersToRoles(string[] userNames, string[] roleNames)
void RemoveUsersFromRoles(string[] userNames, string[] roleNames)
string[] GetUsersInRole(string roleName)
string[] GetAllRoles()
string[] FindUsersInRole(string roleName, string usernameToMatch)
Profile Provider
void Initialize(string name, NameValueCollection config)
SettingsPropertyValueCollection GetPropertyValues(SettingsContext context,
SettingsPropertyCollection properties)
void SetPropertyValues(SettingsContext context,
SettingsPropertyValueCollection properties)
int DeleteProfiles(ProfileInfoCollection profiles)
int DeleteProfiles(string[] usernames)
int DeleteInactiveProfiles(ProfileAuthenticationOption authenticationOption,
DateTime userInactiveSinceDate)
int GetNumberOfInactiveProfiles(ProfileAuthenticationOption authenticationOption,
DateTime userInactiveSinceDate)
ProfileInfoCollection GetAllProfiles(ProfileAuthenticationOption authenticationOption,
int pageIndex, int pageSize, out int totalRecords)
ProfileInfoCollection GetAllInactiveProfiles
(ProfileAuthenticationOption authenticationOption,
DateTime userInactiveSinceDate, int pageIndex,
int pageSize, out int totalRecords)
ProfileInfoCollection FindProfilesByUserName
(ProfileAuthenticationOption authenticationOption,
string usernameToMatch, int pageIndex,
int pageSize, out int totalRecords)
ProfileInfoCollection FindInactiveProfilesByUserName
(ProfileAuthenticationOption authenticationOption,
string usernameToMatch,
DateTime userInactiveSinceDate, int pageIndex,
int pageSize, out int totalRecords)
如何使用提供的解决方案?
此解决方案中包含的三个 providers 是连接的,但如果并非所有 providers 都是必需的,则将它们分开应该不需要太多工作。 有两种使用源代码的方法
- 使用提供的实体模型连接到现有或新的数据库。
- 扩展现有数据库,从而扩展现有实体模型,并将 providers 使用的数据上下文替换为现有数据上下文。
一般来说,必须应用以下步骤才能启动和运行第一种方法
- 创建一个新数据库(例如,*EFDataModel*)。
- 在新数据库上运行位于 *DatabaseScripts* 解决方案文件夹中的 *CreateTables.sql* 脚本。
- 在 *SmartSoft.EFProviders.DataLayer* 项目的 *App.config* 文件中修改实体框架的连接字符串。
- 在 Web 应用程序的 *Web.config* 文件中修改实体框架的连接字符串。
- 在 *Web.config* 中配置 providers 如下
<!-- Membership configuration -->
<membership defaultProvider="EFMembershipProvider" userIsOnlineTimeWindow="15">
<providers>
<add name="EFMembershipProvider"
type="HelveticSolutions.EFProviders.Web.Security.EFMembershipProvider,
HelveticSolutions.EFProviders.Web, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=53fb08796b3f3bb2"
connectionStringName="EFProviderConnection"
enablePasswordRetrieval="true"
enablePasswordReset="true"
requiresQuestionAndAnswer="true"
writeExceptionsToEventLog="true" />
</providers>
</membership>
<machineKey validationKey="C50B3C89CB21F4F1422FF158A5B42D0E8DB8CB5CDA174257
2A487D9401E3400267682B202B746511891C1BAF47F8D25C07F6C39A104696DB51F17C529AD3CABE"
decryptionKey="8A9BE8FD67AF6979E7D20198CFEA50DD3D3799C77AF2B72F"
validation="SHA1"/>
<!-- Role configuration -->
<roleManager enabled="true" defaultProvider="EFRoleProvider">
<providers>
<add name="EFRoleProvider"
type="HelveticSolutions.EFProviders.Web.Security.EFRoleProvider,
HelveticSolutions.EFProviders.Web, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=53fb08796b3f3bb2"
connectionStringName="EFProviderConnection" />
</providers>
</roleManager>
<!-- Profile configuration -->
<profile enabled="true"
defaultProvider="EFProfileProvider"
inherits="EFProvidersWebApplication.MyProfile"
automaticSaveEnabled="true">
<providers>
<add name="EFProfileProvider"
type="HelveticSolutions.EFProviders.Web.Profile.EFProfileProvider,
HelveticSolutions.EFProviders.Web, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=53fb08796b3f3bb2"
connectionStringName="EFProviderConnection"/>
</providers>
</profile>
背景
在可能的情况下,编写 LINQ 查询以使用表达式树而不是委托。 本文很好地描述了差异。
历史
- 2008 年 10 月 29 日 - 发布初始文章
- 2009 年 8 月 1 日 - 新的 `EFRoleProvider` 和 `EFProfileProvider`,改进的 `EFMembershipProvider`
-
2014 年 11 月 14 日 - 命名空间已更正