Click here to Skip to main content
Click here to Skip to main content

ASP.NET Providers for the ADO.NET Entity Framework

By , 2 Aug 2009
 

Introduction

One of the most powerful improvements of ASP.NET 2.0 was truly the introduction of the membership, role and profile providers. They allow to rapidly integrate user management, role based security as well as visitor based page customization into your ASP.NET application. The name already indicates that they all implement the provider model design pattern.

Unfortunately, Microsoft doesn't have these providers ready to download leveraging the ADO.NET Entity Framework.

The downloadable source from this article provides a ready-to-use implementation for the above mentioned providers. The following article gives a quick overview about providers and it describes what it takes to get the provided source up and running.

In order to understand the source, sound knowledge of LINQ is inevitable. Furthermore, it is important that readers understand the philosophy behind ASP.NET providers.The following link gives a good overview of the ASP.NET providers.

Background

Provider Model Design Pattern

provider_overview.JPG

The provider model pattern was designed to provide a configurable component for data access which is defined from the web.config. The Provider interfaces between the Business logic and Data Access. The actual concrete implementation of the provider is defined in the web.config. Custom providers can be built and configured in the web.config without changing the application design. Providers are a subclass of the ProviderBase class and typically instantiated using a factory method.

Various providers for the same purpose can co-exist and easily be configured in the web.config.

Database Schema

The database schema is closely related to the one that gets created by aspnet_regsql.exe:

provider_database_schema.JPG

The resulting Entity Model looks like the following:

provider_entity_model.JPG

Other than Microsoft's ASP.NET providers for SQL, the presented solution here does not use stored procedures. Instead, all the queries are implemented in the respective providers source using LINQ.

Exposed APIs

Membership Provider
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)

How To Use the Provided Solution?

The three in this solution contained providers are connected but it shouldn't be too much work to pull them apart if not all of them are required. There are two ways to use the source:

  1. Use the provided Entity Model to connect to an existing or new database.
  2. Extend an existing database and hence the existing Entity Model and replace the data context used by the providers with the existing data context.

In general, the following steps have to be applied to get the first approach up and running:

  1. Create a new database (e.g., EFDataModel).
  2. Run the CreateTables.sql script located in the DatabaseScripts solution folder on the new database.
  3. Modify the connection string for the Entity Framework in the App.config file of the SmartSoft.EFProviders.DataLayer project.
  4. Modify connection string for the Entity Framework in the Web.config file of the Web application.
  5. Configure the providers in the Web.config as follows:
<!-- Membership configuration -->
<membership defaultProvider="EFMembershipProvider" userIsOnlineTimeWindow="15">
    <providers>
        <add name="EFMembershipProvider" 
             type="SmartSoft.EFProviders.Web.Security.EFMembershipProvider, 
              SmartSoft.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="SmartSoft.EFProviders.Web.Security.EFRoleProvider, 
              SmartSoft.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="SmartSoft.EFProviders.Web.Profile.EFProfileProvider, 
              SmartSoft.EFProviders.Web, Version=1.0.0.0, Culture=neutral, 
              PublicKeyToken=53fb08796b3f3bb2" 
             connectionStringName="EFProviderConnection"/>
    </providers>
</profile>

Background

Wherever possible, LINQ queries were written to use expression trees rather than delegates. This article greatly describes the difference.

History

  • 29/10/2008 - Initial article posted
  • 01/08/2009 - New EFRoleProvider and EFProfileProvider, improved EFMembershipProvider

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Michael Ulmann
Architect Helvetic Solutions
Australia Australia
Member
MCAD, MCPD Web Developer 2.0, MCPD Enterprise Developer 3.5
My company: www.helveticsolutions.com
Hopp Schwiiz Smile | :)

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
Hint: For improved responsiveness ensure Javascript is enabled and choose 'Normal' from the Layout dropdown and hit 'Update'.
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralError, when parse string for serialized Profile fieldsmemberkavittoneghtandday15 Apr '11 - 0:20 
GeneralRe: Error, when parse string for serialized Profile fieldsmemberbleepzter27 Jun '11 - 14:32 
GeneralMigration to EF4 and standart aspnet_regsql genrated structurememberCrazyMasterMC21 Feb '11 - 20:23 
GeneralMy vote of 1membermobasshir15 Oct '10 - 7:09 
GeneralRe: My vote of 1 [modified]memberMichael Ulmann25 Oct '10 - 19:26 
QuestionHow to track anonymous usermemberMember 740954115 Oct '10 - 2:07 
QuestionDataAccess using Stored ProceduresmemberPradeep Babu Yadagani2 Oct '10 - 21:18 
Generalproblem in Upgrade to ASP.NET 2010 [modified]memberir_programmer24 Jun '10 - 0:20 
GeneralErrors in ProfileProvider.GetNumberOfInactiveProfiles(...) [modified]memberasmason6 Apr '10 - 7:16 
GeneralRe: Errors in ProfileProvider.GetNumberOfInactiveProfiles(...)memberMichael Ulmann8 Apr '10 - 20:08 
GeneralErrors in ProfileProvider.GetAllProfiles()memberasmason6 Apr '10 - 7:10 
GeneralErrors in ProfileProvider.GetAllInactiveProfiles(...)memberasmason6 Apr '10 - 7:04 
GeneralErrors in ProfileProvider.FindProfilesByUserName(...)memberasmason6 Apr '10 - 6:49 
GeneralErrors in ProfileProvider FindInactiveProfilesByUserName(...) [modified]memberasmason6 Apr '10 - 5:55 
GeneralError in ProfileProvidermemberasmason6 Apr '10 - 4:20 
QuestionHow do we access the FirstName / LastName properties?memberrcbapb214 Feb '10 - 4:32 
AnswerRe: How do we access the FirstName / LastName properties?memberMichael Ulmann15 Feb '10 - 17:31 
GeneralRe: How do we access the FirstName / LastName properties?memberrcbapb216 Feb '10 - 10:55 
GeneralError in Role providermemberMember 456185410 Dec '09 - 8:40 
GeneralRe: Error in Role providermemberMichael Ulmann10 Dec '09 - 14:04 
GeneralRe: Error in Role providermemberMember 456185410 Dec '09 - 19:19 
QuestionVB.NET Version?memberPeki.HR17 Nov '09 - 3:07 
AnswerRe: VB.NET Version? [modified]memberMichael Ulmann19 Nov '09 - 19:08 
GeneralError in ProfileProvider [modified]memberBidou448 Nov '09 - 21:57 
GeneralRe: Error in ProfileProvidermemberFarshid300315 Feb '11 - 23:40 
GeneralRole provider GetUsersInRole(string roleName) bugmembercoolbest122 Sep '09 - 0:49 
GeneralRe: Role provider GetUsersInRole(string roleName) bugmemberMichael Ulmann22 Sep '09 - 14:39 
GeneralExcellent article, 5*****!memberDrABELL14 Sep '09 - 11:35 
QuestionProfilememberrayburnj9 Sep '09 - 3:56 
AnswerRe: ProfilememberMichael Ulmann17 Sep '09 - 16:00 
GeneralRe: ProfilememberMember 45618549 Dec '09 - 20:27 
GeneralRe: ProfilememberMichael Ulmann9 Dec '09 - 23:45 
GeneralRe: ProfilememberMember 456185410 Dec '09 - 8:43 
GeneralRe: ProfilememberMichael Ulmann10 Dec '09 - 11:32 
GeneralRe: ProfilememberMember 456185410 Dec '09 - 19:20 
Generalhelp in webconfigememberTGiril19 Aug '09 - 0:07 
GeneralConfiguration ErrormemberKevin Slesinsky14 Aug '09 - 6:42 
GeneralRe: Configuration ErrormemberMichael Ulmann16 Aug '09 - 18:40 
GeneralRe: Configuration ErrormemberKevin Slesinsky19 Aug '09 - 8:13 
GeneralUnlockUsermemberKevin Slesinsky20 Aug '09 - 10:32 
GeneralGreat stuff!memberceltonthenet11 Aug '09 - 1:29 
GeneralProfile Provider with EF "normal" SQL Profile tablemembershapper5 Aug '09 - 16:09 
GeneralSQL Scriptmembershapper5 Aug '09 - 3:12 
GeneralThanks. One suggestion and one questionmembershapper3 Aug '09 - 14:54 
GeneralRe: Thanks. One suggestion and one questionmemberMichael Ulmann3 Aug '09 - 16:02 
GeneralRe: Thanks. One suggestion and one questionmembershapper4 Aug '09 - 6:34 
GeneralRe: Thanks. One suggestion and one questionmembershapper4 Aug '09 - 6:36 
GeneralRe: Thanks. One suggestion and one questionmemberMichael Ulmann4 Aug '09 - 20:46 
GeneralRe: Thanks. One suggestion and one questionmembershapper5 Aug '09 - 1:35 
GeneralRe: Thanks. One suggestion and one questionmembershapper5 Aug '09 - 3:11 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130516.1 | Last Updated 2 Aug 2009
Article Copyright 2009 by Michael Ulmann
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid