|
|
|
|
Joined: 3/2/2006
Posts: 223
|
|
|
Does somebody know a way of fast exporting the ProfilePropertyDefinition data ? I have seen a thread (using a view?) about this, but I cannot find it anymore in the forum.
For instance exporting the lastname and firstname like
select
(...as LastName )
(.. as Firstname)
from ...
|
|
|
|
| |
|
|
|
www.nddllc.com Joined: 1/25/2003
Posts: 681
|
|
|
Jelle,
Try this, I have not used it in sometime, but I'll assume that it will meet your needs.
--The aspnet_Profile table contains the following fields: UserId, PropertyNames, PropertyValuesString, PropertyValuesBinary, and LastUpdatedDate. The PropertyNames field contains a string delimited with colons (:) that identify which profile fields are stored, what their datatype is and their offset and length. For instance, in the following example it shows us that the Region field is a string field (S) starting at postion 32 and is 7 characters long.
--Ok, from the previous page we now know where the data is and how it's stored, but how do we get at that from T-SQL. SQL Server 2000 brought us UDF's (User Defined Functions) which allow us to bundle complex logic into reusable functions which we can use directly in SQL queries. I'm not going to go into the nitty gritty of UDF's here but we are going to be using two different ones to get at the data.
--The first one we'll need is one that will allow us to grab fields of delimited data from a string. Once we have the field offset and length data string such as 32:7, we will need this function to parse this into two separate integers, namely 32 and 7 so we can use the SUBSTRING function to grab the data from the PropertyValuesString field. The function to do that is here:
--RUN FIRST
CREATE FUNCTION dbo.fn_GetElement
(
@ord AS INT,
@str AS VARCHAR(8000),
@delim AS VARCHAR(1) )
RETURNS INT
AS
BEGIN
-- If input is invalid, return null.
IF @str IS NULL
OR LEN(@str) = 0
OR @ord IS NULL
OR @ord < 1
-- @ord > [is the] expression that calculates the number of elements.
OR @ord > LEN(@str) - LEN(REPLACE(@str, @delim, '')) + 1
RETURN NULL
DECLARE @pos AS INT, @curord AS INT
SELECT @pos = 1, @curord = 1
-- Find next element's start position and increment index.
WHILE @curord < @ord
SELECT
@pos = CHARINDEX(@delim, @str, @pos) + 1,
@curord = @curord + 1
RETURN CAST(SUBSTRING(@str, @pos, CHARINDEX(@delim, @str + @delim, @pos) - @pos) AS INT)
END
--This function takes 3 parameters; @ord, @str and @delim. @ord is the field number you wish to return, @str is the string that you wish to parse, and @delim is the delimiter you are folding the string with. This is a very general UDF that can be used to return delimited fields for any t-sql and isn't just handy for this task. I found the source for this function at the Windows IT Pro site in an article by Itzik Ben-Gan. We'll be calling this function in our next function.
--The last UDF we need, is one that will take the field values from aspnet_Profile and parse them to return the proper data. This one, named fn_GetProfileElement also takes 3 parameters; @fieldName (the profile fieldname we want to grab), @fields (the string from PropertyNames), and @values (the string values from PropertyValuesString).
--RUN SECOND
CREATE FUNCTION dbo.fn_GetProfileElement
(
@fieldName AS NVARCHAR(100),
@fields AS NVARCHAR(4000),
@values AS NVARCHAR(4000))
RETURNS NVARCHAR(4000)
AS
BEGIN
-- If input is invalid, return null.
IF @fieldName IS NULL
OR LEN(@fieldName) = 0
OR @fields IS NULL
OR LEN(@fields) = 0
OR @values IS NULL
OR LEN(@values) = 0
RETURN NULL
-- locate FieldName in Fields
DECLARE @fieldNameToken AS NVARCHAR(20)
DECLARE @fieldNameStart AS INTEGER, @valueStart AS INTEGER, @valueLength AS INTEGER
-- Only handle string type fields (:S:)
SET @fieldNameStart = CHARINDEX(@fieldName + ':S',@Fields,0)
-- If field is not found, return null
IF @fieldNameStart = 0 RETURN NULL
SET @fieldNameStart = @fieldNameStart + LEN(@fieldName) + 3
-- Get the field token which I've defined as the start of the field offset to the end of the length
SET @fieldNameToken = SUBSTRING(@Fields,@fieldNameStart,LEN(@Fields)-@fieldNameStart)
-- Get the values for the offset and length
SET @valueStart = dbo.fn_getelement(1,@fieldNameToken,':')
SET @valueLength = dbo.fn_getelement(2,@fieldNameToken,':')
-- Check for sane values, 0 length means the profile item was stored, just no data
IF @valueLength = 0 RETURN ''
-- Return the string
RETURN SUBSTRING(@values, @valueStart+1, @valueLength)
END
--Now, all we have to do is provide the proper call in our T-SQL query to this function and we should have our data. To do this, simply call it as follows:
SELECT dbo.fn_GetProfileElement('PostalCode',PropertyNames,PropertyValuesString) FROM aspnet_Profile
--In this example, I'm grabbing only the PostalCode field, but you could grab any field that is stored in the profile data. There are many other fields you can grab as shown in the following list: Unit, Street, City, Region, PostalCode, Country, Telephone, Fax, Cell, Website, IM, TimeZone and PreferredLocale.
--here's another sample which shows the proper joins to get at most of the information, plus a call to our new function to grab the profile data field named PostalCode.
select users.userid, users.username, users.firstname, users.lastname, roles.rolename, aspnet_membership.email,
dbo.fn_GetProfileElement('PostalCode',PropertyNames,PropertyValuesString) PostalCode
from users
inner join userroles on users.userid = userroles.userid
inner join roles on userroles.roleid = roles.roleid
inner join aspnet_users on users.username = aspnet_users.username
inner join aspnet_membership on aspnet_users.userid = aspnet_membership.userid
inner join aspnet_profile on aspnet_profile.userid = aspnet_membership.userid
--CREATE view based on code
CREATE VIEW dbo.vw_ProfileProperties
AS
SELECT
Users_1.userid,
dbo.fn_GetProfileElement('FirstName', PropertyNames, PropertyValuesString) AS FirstName,
dbo.fn_GetProfileElement('LastName', PropertyNames, PropertyValuesString) AS LastName,
dbo.fn_GetProfileElement('Street', PropertyNames, PropertyValuesString) AS Street,
dbo.fn_GetProfileElement('City', PropertyNames, PropertyValuesString) AS City,
dbo.fn_GetProfileElement('Region', PropertyNames, PropertyValuesString) AS Region,
dbo.fn_GetProfileElement('Country', PropertyNames, PropertyValuesString) AS Country,
dbo.fn_GetProfileElement('PostalCode', PropertyNames, PropertyValuesString) AS PostalCode,
dbo.fn_GetProfileElement('Telephone', PropertyNames, PropertyValuesString) AS Telephone
FROM
dbo.Users Users_1 INNER JOIN
dbo.aspnet_Users aspnet_Users_1 ON Users_1.username = aspnet_Users_1.username INNER JOIN
dbo.aspnet_Membership aspnet_Membership_1 ON aspnet_Users_1.userid = aspnet_Membership_1.userid INNER JOIN
dbo.aspnet_Profile aspnet_Profile_1 ON aspnet_Profile_1.userid = aspnet_Membership_1.userid
|
|
|
|
| |
|
|
|
|
erikvanballegoij.com Joined: 4/7/2004
Posts: 4445
|
|
|
Chris, as of dnn 3.3.0 / 4.3.0, this script will no longer work, because profiles are no longer stored in the aspnet tables, the DNNMembership provider uses its own tables now.....
Erik van Ballegoij, Former DNN Corp. Employee and DNN Expert
DNN Blog | Twitter: @erikvb | LinkedIn:
|
|
|
|
| |
|
|
Brillnat.com Joined: 12/17/2004
Posts: 175
|
|
|
there is a view so you can select * from vw_Users
it will return a recordset, with some of the columns being:
UserId, PortalId, Username, FirstName, LastName, DisplayName,...
While not all the profile fields you do get something. Check it out
mj
|
|
|
|
| |
|
|
|
Joined: 3/2/2006
Posts: 223
|
|
|
Hi,
I build own SP's based on functions (so no views). I seems that getting 22 user properties is quite resource/ performance consuming. I was wondering how Microsoft is doing this in it's SharePoint or Microsoft Dynamics. Does anybody have a clue?
I have posted my concept sp's and functions below. It seems in the DNN store the billing and deliveryaddress can be either stored in the store address, but also the registration address of DNN. This makes the collection of data for export quite cumbersome and performance consuming. Storing user data in the profileProperties seems to have some performance drawback. Does anybody has suggestion on how to improve speed sp's below?
Jelle
==
set ANSI_NULLS ON QUOTED_IDENTIFIER ON FUNCTION [dbo].[V4A_DNN_FN_V4A_GetProfilePropertyDataByUserId]int,@PropertyName nvarchar(50) NVARCHAR(MAX)DECLARE @PropertyValue NVARCHAR(MAX)--LEAVE OUT IN CASE OF PERFORMANCE CONSIDERATIONSIF @PropertyName IS NULLOR LEN(@PropertyName) = 0RETURN -1--LEAVE OUT IN CASE OF PERFORMANCE CONSIDERATIONSIF @UserId IS NULLSET @UserId = -1SET @PropertyValue = (SELECT V4A_DNN_UserProfile.PropertyValueFROM INNER JOIN V4A_DNN_UserProfile ON V4A_DNN_ProfilePropertyDefinition.PropertyDefinitionID = V4A_DNN_UserProfile.PropertyDefinitionIDWHERE (V4A_DNN_UserProfile.UserId = @UserId) AND (V4A_DNN_ProfilePropertyDefinition.PropertyName = @PropertyName)) RETURN @PropertyValue
set
GO
/*
CREATED: JO 20061206_01
HISTORY:
CHANGED: -
*/
ALTER
(
@UserId
)
RETURNS
AS
BEGIN
V4A_DNN_ProfilePropertyDefinition
END
==
ANSI_NULLS ON QUOTED_IDENTIFIER ON FUNCTION [dbo].[V4A_DNN_FN_V4A_GetProfilePropertyDataById]INT,@PropertyDefinitionId INT NVARCHAR(MAX)DECLARE @PropertyValue NVARCHAR(MAX)--LEAVE OUT IN CASE OF PERFORMANCE CONSIDERATIONSIF @UserId IS NULLSET @UserId = -1SET @PropertyValue = (SELECT FROM WHERE (UserID = @UserId) AND (PropertyDefinitionID = @PropertyDefinitionId) ) RETURN @PropertyValue
set
set
GO
/*
CREATED: JO 20061206_01
HISTORY:
CHANGED: -
*/
ALTER
(
@UserId
)
RETURNS
AS
BEGIN
PropertyValue
V4A_DNN_UserProfile
END
==
ANSI_NULLS ON QUOTED_IDENTIFIER ON PROCEDURE [dbo].[V4A_DNN_V4A_TP_DataExchange_Customer_Export]INT = -1DECLARE @FirstNameId AS INTDECLARE @LastNameId AS INTDECLARE @PostalCodeId AS INTDECLARE @PreferredLocale AS INTSET @FirstNameId = [dbo].[V4A_DNN_GetProfilePropertyDefinitionID](@PortalId,'FirstName')SET @LastNameId = [dbo].[V4A_DNN_GetProfilePropertyDefinitionID](@PortalId,'LastName')SET @PostalCodeId = [dbo].[V4A_DNN_GetProfilePropertyDefinitionID](@PortalId,'PostalCode')SET @PreferredLocale = [dbo].[V4A_DNN_GetProfilePropertyDefinitionID](@PortalId,'PreferredLocale')PRINT '@FirstNameId : ' + CONVERT(NVARCHAR, @FirstNameId)PRINT '@LastNameId : ' + CONVERT(NVARCHAR, @LastNameId)PRINT '@PostalCodeId : ' + CONVERT(NVARCHAR, @PostalCodeId)PRINT '@PreferredLocale : ' + CONVERT(NVARCHAR, @PreferredLocale).UserID,U.UserName,U.FirstName,U.LastName,U.IsSuperUser,U.Email,U.DisplayName,U.UpdatePassword,UP.UserPortalId,UP.CreatedDate,UP.Authorised,[dbo].[V4A_DNN_FN_V4A_GetProfilePropertyDataById](U.userid, @FirstNameId) AS FirstName,[dbo].[V4A_DNN_FN_V4A_GetProfilePropertyDataById](U.userid, @PostalCodeId) AS PostalCode,[dbo].[V4A_DNN_FN_V4A_GetProfilePropertyDataById](U.userid, @PreferredLocale) AS PreferredLocale.V4A_DNN_Users ULEFT JOIN V4A_DNN_UserPortals UP on U.UserId = UP.UserId.PortalId = @PortalId
===
@return_value int @return_value = [dbo].[V4A_DNN_V4A_TP_DataExchange_Customer_Export]= 0 'Return Value' = @return_value
set
set
GO
/*
CREATED JO 20061207
HISTORY:
20061207_01 JO Added UserPortal table in query
-
*/
ALTER
(
@PortalId
)
AS
SELECT
U
-- ,[dbo].[V4A_DNN_FN_V4A_GetProfilePropertyDataById](U.userid, @LastNameId) AS LastName
--dbo.V4A_DNN_GetProfileElement('LastName', PropertyName, PropertyValuesString) AS LastName,
--dbo.V4A_DNN_GetProfileElement('Street', PropertyName, PropertyValuesString) AS Street,
--dbo.V4A_DNN_GetProfileElement('City', PropertyName, PropertyValuesString) AS City,
--dbo.V4A_DNN_GetProfileElement('Region', PropertyName, PropertyValuesString) AS Region,
--dbo.V4A_DNN_GetProfileElement('Country', PropertyName, PropertyValuesString) AS Country,
--dbo.V4A_DNN_GetProfileElement('PostalCode', PropertyName, PropertyValuesString) AS PostalCode,
--dbo.V4A_DNN_GetProfileElement('Telephone', PropertyName, PropertyValuesString) AS Telephone
FROM
dbo
WHERE
UP
DECLARE
EXEC
@PortalId
SELECT
|
|
|
|
| |