• Microsoft .NET
  • ASP.NET
  • Контекстно-зависимая помощь для веб-страницы в ASP.NET 2.0

Поставщики ASP.NET для каркаса сущностей ADO.NET

Внедрение каркаса сущностей ADO.NET создало потребность в поставщиках ASP.NET, таких как членство, роль и профиль, использующих эту новую технологию.

•    Скачать исходники - 45.58 Кб

Введение

Одним из наиболее мощных улучшений ASP.NET 2.0 было введение поставщиков членства, роли и профиля. Они позволяют быстро встраивать управление пользователями, защиту на основе роли и индивидуализацию страницы в зависимости от посетителя в ваше приложение ASP.NET. Имя уже говорит, что все они реализуют шаблон разработки модели поставщика.
К сожалению, Microsoft не имеет этих готовых для скачивания поставщиков, использующих каркас сущностей ADO.NET.
Скачиваемые исходники из данной статьи дают готовую к применению реализацию вышеуказанных поставщиков. Следующая статья дает беглый обзор поставщиков и описывает все, что требуется для запуска и работы предоставленных исходников.

Для понимания исходников требуется хорошее знание LINQ. Более того, читатели должны понимать принципы устройства поставщиков ASP.NET. Следующая ссылка дает хорошее представление о поставщиках ASP.NET.

Объяснение

Шаблон разработки модели поставщика


 
Шаблон модели поставщика предоставляет конфигурируемый компонент для доступа к данным, определенный из web.config. Поставщик согласовывает бизнес-логику и доступ к данным. Реальная конкретная реализация поставщика определяется в web.config. Можно создавать и настраивать собственные поставщики в web.config без изменения архитектуры приложения. Поставщики являются подклассом ProviderBase, и их экземпляры обычно создаются с помощью генерирующего метода.

Разные поставщики для одинаковой цели могут сосуществовать и легко настраиваются в web.config.

Схема базы данных

Схема базы данных тесно связана со схемой, создаваемой aspnet_regsql.exe:

Итоговая модель сущностей выглядит так:

В отличие от поставщиков Microsoft ASP.NET для SQL, представленное здесь решение не использует хранимые процедуры. Наоборот, все запросы реализуются в исходном коде соответствующих поставщиков с помощью LINQ.

Предоставляемые 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)

Поставщик роли

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)

Поставщик профиля

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)

Как использовать предоставленное решение?

Три поставщика, входящие в данное решение, соединены, но разделить их не составит труда, если не все из них нужны.

Есть два способа использования исходников:
1.    Использовать предоставленную модель сущностей для подключения к имеющейся или новой базе данных.
2.    Расширить имеющуюся базу данных и имеющуюся модель сущностей и заменить контекст данных, используемый поставщиками, на имеющийся контекст данных.

Как правило, надо выполнить следующие шаги, чтобы заставить первый способ работать:
1.    Создать новую базу данных (например, EFDataModel).
2.    Запустить скрипт CreateTables.sql, находящийся в папке решения DatabaseScripts, для новой базы данных.
3.    Изменить строку подключения для каркаса сущностей в файле App.config проекта SmartSoft.EFProviders.DataLayer.
4.    Изменить строку подключения для каркаса сущностей в файле Web.config веб-приложения.
5.    Настроить поставщики в Web.config следующим образом:

<!—Конфигурация членства -->
<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"/>
<!—Конфигурация роли -->
<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 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>

Объяснение

По возможности были написаны запросы LINQ, чтобы использовать деревья выражений вместо делегатов.