ASP.NET SQL Profile Provider - Does the ProfileBase.Create() method hit DB?

Mike M picture Mike M · Jul 14, 2009 · Viewed 7.1k times · Source

I am working with the SQLMemebershipProvider and using Profiles. I have a custom class called UserProfile that inherits from the ProfileBase class and I use this to set custom properties like "FullName". I am wanting to loop through all the users in the database and get access to their profile properties. On each iteration I am calling ProfileBase.Create() to get a new profile and then access the properties.

It looks to me like every time ProfileBase.Create() is called it hits my SQL database. But I am just looking for confirmation of this. So, does anyone know if this does in fact hit the DB each time?

And better yet, does anyone have a better solution of how I could make one call to the DB to get all users with their custom profile attributes?

I know I could write my own stored proc, but I am wondering if there is a way built in to the Membership Provider.

Answer

Masterfu picture Masterfu · Nov 16, 2009

Mike, I believe what you observed is true. I am working with a ProfileProvider that uses Azure TableStorage as data store. I wanted to get a list of user profiles from database and merge them with information from membership provider. It took some time until I realized that calling ProfileBase.Create() with a username as argument performs a lookup against TableStorage and actually retrieves the data associated with that username. As far as I'm concerned, calling this method Create() is misleading, I would expect Load() or Get(). Currently my code looks like this:

    public IEnumerable<AggregatedUser> GetAllAggregatedUsers()
    {
        ProfileInfoCollection allProfiles = this.GetAllUsersCore(
             ProfileManager.GetAllProfiles(ProfileAuthenticationOption.All)
        );

        //AggregatedUser is simply a custom Class that holds all the properties (Email, FirstName) that are being used
        var allUsers = new List<AggregatedUser>();

        AggregatedUser currentUser = null;
        MembershipUser currentMember = null;
        foreach (ProfileInfo profile in allProfiles)
        {
            currentUser = null;
            // Fetch profile information from profile store
            ProfileBase webProfile = ProfileBase.Create(profile.UserName);
            // Fetch core information from membership store
            currentMember = Membership.FindUsersByName(profile.UserName)[profile.UserName];
            if (currentMember == null)
                continue;

            currentUser = new AggregatedUser();
            currentUser.Email = currentMember.Email;
            currentUser.FirstName = GetStringValue(webProfile, "FirstName");
            currentUser.LastName = GetStringValue(webProfile, "LastName");
            currentUser.Roles = Roles.GetRolesForUser(profile.UserName);
            currentUser.Username = profile.UserName;
            allUsers.Add(currentUser);
        }

        return allUsers;
    }

    private String GetStringValue(ProfileBase profile, String valueName)
    {
        if (profile == null)
            return String.Empty;
        var propValue = profile.PropertyValues[valueName];
        if (propValue == null)
            return String.Empty;

        return propValue.PropertyValue as String;
    }

Is there a better (more straightforward, more performant) way to

  1. retrieve all the custom profile information from profile provider and
  2. merge them with membership provider info to show them e.g. in an administrator page?

I have had a look at Web Profile Builder but IMO this only provides design-time intellisense for custom profile properties by generating a proxy class.