Please login with Twitter.
27

Every once and a while you probably find yourself needing to create an overview of DNN users and some of their profile properties. For instance when your client wants to have that data in an excel spreadsheet….

Profile properties in DNN are both a blessing and a curse. Although they allow you to quickly add attributes to a user, such as Companyname, Picture, etc., they are hard to use in SQL. That’s because of the structure of the data: there’s a table that holds all property definitions, and there’s another table that holds the data.

DNN Profile Properties

In the past, I have been using a quick and dirty way: just creating a specific view for each profile property I wanted to include in my select. That would work like this: let’s suppose I have a profile property named “CompanyName”. I can then create a view like this:

CREATE VIEW [dbo].[vwCompanyName]
ASSELECT     UP.UserID, PPD.PortalID, UP.PropertyValue AS CompanyNameFROM         dbo.ProfilePropertyDefinition AS PPD INNER JOIN
dbo.UserProfile AS UP ON PPD.PropertyDefinitionID = UP.PropertyDefinitionIDWHERE     (PPD.PropertyName = 'CompanyName') AND (PPD.PortalID = 0)

 

This allows me to create a new view that includes the companyname with the user’s info:

CREATE VIEW [dbo].[vw_UsersComplete]
ASSELECT     dbo.vw_Users.UserId, dbo.vw_Users.PortalId, dbo.vw_Users.Username, dbo.vw_Users.FirstName, dbo.vw_Users.LastName, 
dbo.vw_Users.DisplayName, dbo.vw_Users.IsSuperUser, dbo.vw_Users.Email, dbo.vw_Users.AffiliateId, dbo.vw_Users.UpdatePassword, 
dbo.vw_Users.Authorised, dbo.vwCompanyName.CompanyNameFROM         dbo.vw_Users INNER JOIN
dbo.vwCompanyName ON dbo.vw_Users.PortalId = dbo.vwCompanyName.PortalID AND dbo.vw_Users.UserId = dbo.vwCompanyName.UserID

 

(vw_Users is a DotNetNuke core SQL View, which joins the tables Users and UserPortals, resulting in a view with user information AND information about which portal users belong to.)

I now have a view of all user information including the company name.

 

Doing this for one profile property is not so much work, however, if there are many profile properties to include, creating a seperate view for all of them is rather tedious. Creating a user defined function (UDF) that returns a table is much less work. The UDF I created subsequently is this:

CREATE FUNCTION [dbo].[udf_UserProfileField]
(
@PropertyName NVARCHAR(50)
)
RETURNS @ProfileFieldTable TABLE
(
PortalId INT,
UserID INT,
PropertyName NVARCHAR(50),
PropertyValue NVARCHAR(3750)
)
AS BEGIN
INSERTINTO @ProfileFieldTableSELECT  PPD.PortalID,
UP.UserID,
PPD.PropertyName,
UP.PropertyValueFROM    dbo.Users AS UINNER JOIN dbo.UserProfile AS UP ON U.UserID = UP.UserIDINNER JOIN dbo.ProfilePropertyDefinition AS PPD ON UP.PropertyDefinitionID = PPD.PropertyDefinitionIDWHERE   ( PPD.PropertyName = @PropertyName )
RETURN 
END

 

This UDF works essentially the same as the previously created view vwCompanyName. The function takes the parameter PropertyName. This allows us to easily use this UDF in combination with vw_Users. Just start creating a view like you would create any view in SQL Server, using SQL Server Management Studio. Start by adding the view “vw_Users”:

image 

next, add the function udf_UserProfileField (in fact, add it for as many profile fields you want to include in your view…):

image 

For this sample I added the function twice. For clarity i then changed the names of the 2 table functions to “UserCompany” and “UserCity”. Next, i added the relationships to the vw_Users view. Remember that the relationships are definined by both PortalId and UserId (So we know for sure that the profile properties we link to users are coming from the right portal!). Also, I selected the relationship option to show all records from the vw_Users view, since not every user might have values for all profile properties. This way, the view will return empty values for those users. The final view looks like this:

 

vwUsersComplete

The quickest way to repeat this result is to just copy and run the below sql statement:

CREATE VIEW [dbo].[vwUsersComplete]
ASSELECT     U.UserId, U.PortalId, U.Username, U.FirstName, U.LastName, U.DisplayName, U.IsSuperUser, U.Email, U.AffiliateId, U.UpdatePassword, U.Authorised, 
UserCompany.PropertyValue AS Company, UserCity.PropertyValue AS CityFROM         dbo.udf_UserProfileField('City') AS UserCity RIGHT OUTER JOIN
dbo.vw_Users AS U ON UserCity.PortalId = U.PortalId AND UserCity.UserID = U.UserId LEFT OUTER JOIN
dbo.udf_UserProfileField('Company') AS UserCompany ON U.UserId = UserCompany.UserID AND U.PortalId = UserCompany.PortalId

As you can see the above view uses the same UDF 2 times, and that’s where the advantage is. You can now easily create views that link your users to their profile properties. The posibilities are endless, eg, you might want to use the DotNetNuke Reports module to render the results of this view to a DNN page, while using the Reports Module’s powerful rendering capabilities.

Posted in: DotNetNuke
  

Comments

Will Strohl
Monday, April 27, 2009 10:51 PM
Great post, and great timing. I was going to have to do something like this soon with one of my open source modules.
Antony S
# Antony S
Monday, April 27, 2009 11:05 PM
Thanks Erik, I have been spending hours trying to get something like this.
Joe LaTulippe
# Joe LaTulippe
Friday, October 16, 2009 10:54 PM
Hey Erik, It was suggested that this process would be a good way to build a "Birthday Announcement" on my DNN 4.9.5 website, using our staff's DNN profiles, including their date of birth. Can you elaborate on implementing your suggestions in this manner?

Post Comment

Name (required)

Email (required)

Website

CAPTCHA image
Enter the code shown above: