views:

1714

answers:

2

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.

A: 

You don't persist to the database until you call Save:

The Save method writes modified profile property values to the data source. The profile provider can reduce the amount of activity at the data source by performing updates only when the IsDirty property is set to true. This is the case for the default SqlProfileProvider.

Andrew Hare
I'm not calling the Save method. I am only trying to retrieve the profiles and their custom properties.
Mike M
+2  A: 

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.

Masterfu
Thank you for the clarification. Much appreciated.
Mike M