1

在我的 ASP.Net Framework 4 Web 应用程序项目(VS 2010)中,我使用的是 SqlTableProfileProvider(http://www.asp.net/downloads/sandbox/table-profile-provider-samples)。我让它与一组自定义属性(如 FirstName、LastName、FavoritePizzaTopping 等)配合得非常好。

但是,我想实现一个 ArrayList、List、Dictionary 或 Collection 类型的多值配置文件属性(以推荐为准)。

该属性将存储与用户关联的品牌列表。我在数据库中有一个存储 UserId 和 BrandId 的表,但我不确定如何实现这个概念。

我查看了http://msdn.microsoft.com/en-us/library/d8b58y5d(v=vs.100).aspx我的属性未在 web.config 中定义,它们在 ProfileCommon : ProfileBase 中定义

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Profile;
using System.Web.Security;
using AbcProfileProvider;

namespace Abc.Profiles
{
    public class ProfileCommon : ProfileBase
    {
        public static ProfileCommon GetProfile()
        {
            return Create(HttpContext.Current.Request.IsAuthenticated ?
               HttpContext.Current.User.Identity.Name : HttpContext.Current.Request.AnonymousID,
               HttpContext.Current.Request.IsAuthenticated) as ProfileCommon;
        }

        public static ProfileCommon GetUserProfile(string username)
        {
            return Create(username) as ProfileCommon;
        }

        public static ProfileCommon GetUserProfile()
        {
            return Create(Membership.GetUser().UserName) as ProfileCommon;
        }

        [CustomProviderData("FirstName;nvarchar")]
        public string FirstName
        {
            get { return ((string)(base["FirstName"])); }
            set { base["FirstName"] = value; Save(); }
        }

        [CustomProviderData("LastName;nvarchar")]
        public string LastName
        {
            get { return ((string)(base["LastName"])); }
            set { base["LastName"] = value; Save(); }
        }

        [CustomProviderData("Address1;nvarchar")]
        public string Address1
        {
            get { return ((string)(base["Address1"])); }
            set { base["Address1"] = value; Save(); }
        }

        [CustomProviderData("Address2;nvarchar")]
        public string Address2
        {
            get { return ((string)(base["Address2"])); }
            set { base["Address2"] = value; Save(); }
        }

        [CustomProviderData("City;nvarchar")]
        public string City
        {
            get { return ((string)(base["City"])); }
            set { base["City"] = value; Save(); }
        }

        [CustomProviderData("State;nvarchar")]
        public string State
        {
            get { return ((string)(base["State"])); }
            set { base["State"] = value; Save(); }
        }

        [CustomProviderData("ZipCode;nvarchar")]
        public string ZipCode
        {
            get { return ((string)(base["ZipCode"])); }
            set { base["ZipCode"] = value; Save(); }
        }

        [CustomProviderData("Phone;nvarchar")]
        public string Phone
        {
            get { return ((string)(base["Phone"])); }
            set { base["Phone"] = value; Save(); }
        }

        [CustomProviderData("Fax;nvarchar")]
        public string Fax
        {
            get { return ((string)(base["Fax"])); }
            set { base["Fax"] = value; Save(); }
        }

        [CustomProviderData("Email;nvarchar")]
        public string Email
        {
            get { return ((string)(base["Email"])); }
            set { base["Email"] = value; Save(); }
        }

        [CustomProviderData("Brands")]
        public List<Brand> Brands
        {
            get { return ((List<Brand>)(base["Brands"])); }
            set { base["Brands"] = value; Save(); }
        }

        [CustomProviderData("Territories")]
        public List<Territory> Territories
        {
            get { return ((List<Territory>)(base["Territories"])); }
            set { base["Territories"] = value; Save(); }
        }
    }
}

我相信解决方案位于 SqlProfileProvider.cs 中,但我不确定如何实现它,以下是该文件中的两种方法(我会发布整个文件,但存在限制):

    public override SettingsPropertyValueCollection GetPropertyValues(SettingsContext context, SettingsPropertyCollection collection) {
        SettingsPropertyValueCollection svc = new SettingsPropertyValueCollection();

        if (collection == null || collection.Count < 1 || context == null)
            return svc;

        string username = (string)context["UserName"];
        if (String.IsNullOrEmpty(username))
            return svc;

        SqlConnection conn = null;
        try {
            conn = new SqlConnection(_sqlConnectionString);
            conn.Open();

            GetProfileDataFromTable(collection, svc, username, conn);
        }
        finally {
            if (conn != null) {
                conn.Close();
            }
        }

        return svc;
    }

    private void GetProfileDataFromTable(SettingsPropertyCollection properties, SettingsPropertyValueCollection svc, string username, SqlConnection conn) {
        List<ProfileColumnData> columnData = new List<ProfileColumnData>(properties.Count);
        StringBuilder commandText = new StringBuilder("SELECT u.UserID");
        SqlCommand cmd = new SqlCommand(String.Empty, conn);

        int columnCount = 0;
        foreach (SettingsProperty prop in properties) {
            SettingsPropertyValue value = new SettingsPropertyValue(prop);
            svc.Add(value);

            string persistenceData = prop.Attributes["CustomProviderData"] as string;
            // If we can't find the table/column info we will ignore this data
            if (String.IsNullOrEmpty(persistenceData)) {
                // REVIEW: Perhaps we should throw instead?
                continue;
            }
            string[] chunk = persistenceData.Split(new char[] { ';' });
            if (chunk.Length != 2) {
                // REVIEW: Perhaps we should throw instead?
                continue;
            }
            string columnName = chunk[0];
            string columnType = chunk[1];

            if (columnType == "Table")
            {
                continue;
            }
            // REVIEW: Should we ignore case?
            SqlDbType datatype = (SqlDbType)Enum.Parse(typeof(SqlDbType), chunk[1], true);

            columnData.Add(new ProfileColumnData(columnName, value, null /* not needed for get */, datatype));
            commandText.Append(", ");
            commandText.Append("t."+columnName);
            ++columnCount;
        }

        commandText.Append(" FROM "+_table+" t, vw_aspnet_Users u WHERE u.ApplicationId = '").Append(AppId);
        commandText.Append("' AND u.UserName = LOWER(@Username) AND t.UserID = u.UserID");
        cmd.CommandText = commandText.ToString();
        cmd.CommandType = CommandType.Text;
        cmd.Parameters.AddWithValue("@Username", username);
        SqlDataReader reader = null;

        try {
            reader = cmd.ExecuteReader();
            //If no row exists in the database, then the default Profile values
            //from configuration are used.
            if (reader.Read()) {
                Guid userId = reader.GetGuid(0);
                for (int i = 0; i < columnData.Count; ++i) {
                    object val = reader.GetValue(i+1);
                    ProfileColumnData colData = columnData[i];
                    SettingsPropertyValue propValue = colData.PropertyValue;

                    //Only initialize a SettingsPropertyValue for non-null values
                    if (!(val is DBNull || val == null))
                    {
                        propValue.PropertyValue = val;
                        propValue.IsDirty = false;
                        propValue.Deserialized = true;
                    }
                }

                // need to close reader before we try to update the user
                if (reader != null) {
                    reader.Close();
                    reader = null;
                }

                UpdateLastActivityDate(conn, userId);
            }
        }
        finally {
            if (reader != null) {
                reader.Close();
            }
        }
    }

这是 web.config 的相关部分:

<membership>
  <providers>
    <clear />
    <add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="ApplicationServices" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="/" />
  </providers>
</membership>
<profile enabled="true" defaultProvider="TableProfileProvider" inherits="Abc.Profiles.ProfileCommon, AbcProfileProvider">
  <providers>
    <clear />
    <add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="ApplicationServices" applicationName="/" />
    <add name="TableProfileProvider" type="Abc.ProfileProviders.SqlTableProfileProvider, AbcProfileProvider" connectionStringName="ApplicationServices" table="MembershipProfiles" applicationName="/" />
    <add name="StoredProcedureProfileProvider" type="Abc.ProfileProviders.SqlStoredProcedureProfileProvider, AbcProfileProvider" connectionStringName="ApplicationServices" setProcedure="setCustomProfileData" readProcedure="getCustomProfileData" applicationName="/" />
  </providers>
</profile>
<roleManager defaultProvider="NetSqlAzManRoleProvider" enabled="true" cacheRolesInCookie="false" cookieName=".ASPROLES" cookieTimeout="30" cookiePath="/" cookieRequireSSL="false" cookieSlidingExpiration="true" cookieProtection="All">
  <providers>
    <clear />
    <add connectionStringName="ApplicationServices" applicationName="/" name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider" />
    <add applicationName="/" name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider" />
    <add name="NetSqlAzManRoleProvider" type="NetSqlAzMan.Providers.NetSqlAzManRoleProvider" connectionStringName="NetSqlAzManConnectionString" storeName="Abc Authorization Store" applicationName="The App" userLookupType="DB" defaultDomain="" UseWCFCacheService="False" />
  </providers>
</roleManager>

我希望 StackOverflow 上的某个人已经实现了类似的东西,或者可以为我指明正确的方向。

谢谢!

4

0 回答 0