Loesung: Suchen in der ASPNET_PROFILE Table / DotNetNuke Profil

So, nach ein wenig google etwas Arbeit habe ich jetzt ein Lösung gefunden, die sogar recht performant aussieht.

Zunächst noch ein paar Basics:

Die Tabelle ASPNET_PROFILE beinhaltet folgende Felder:

  • UserId
  • PropertyNames
  • PropertyValuesString
  • PropertyValuesBinary
  • LastUpdatedDate

Das Feld PropertyNames beinhaltet eine mit ":" separierte Zeichenfolge, die definiert welche Benutzereigenschaften / -properties gespeichert werden. Zusätzlich wird die Position dort angegeben. Ein Beispiel:

FirstName:S:39:7

Dieser (Teil-)Eintrage besagt das die Property den Namen "FirstName" hat, vom Typ String "S" ist, an der Postion 39 anfängt und 7 Zeichen lang ist.

Um nun einzelene Daten zur extrahieren, habe ich mir eine die Funktionalität der UDF (User Defined Functions) vom Microsoft SQL Server bzw. der MSDE zu nutze gemacht. Diese Funktionen können direkt aus SQL-Statements aufgerufen werden.

CREATE FUNCTION dbo.GaliNeo_UDF_GetElement
(
@ord AS INT,
@strToParse AS VARCHAR(8000),
@seperator AS VARCHAR(1)
)
RETURNS INT
AS
BEGIN

  -- Wenn die Eingabeparatemer null sind, wird auch null zurück gegeben
  IF  @strToParse IS NULL
      OR LEN(@strToParse) = 0
      OR @ord IS NULL
      OR @ord < 1
       OR @ord > LEN(@strToParse) - LEN(REPLACE(@strToParse, @seperator, '')) + 1
    RETURN NULL

  DECLARE @ipos AS INT, @curord AS INT

  SELECT @ipos = 1, @curord = 1

  -- nächsts Element suchen
  WHILE @curord < @ord
    SELECT
      @ipos    = CHARINDEX(@seperator, @strToParse, @ipos) + 1,
      @curord = @curord + 1
  RETURN    CAST(SUBSTRING(@strToParse, @ipos, CHARINDEX(@seperator, @strToParse + @seperator, @ipos) - @ipos) AS INT)
END

Die GaliNeo_UDF_GetElement ist eine sehr allgemein Funktion um mit separierte Strings in SQL-Queries zu arbeiten. Sehr hilfreich war dabei ein Artikel auf der Seite WindowsItPro.

Diese Funktion können wir nun in der eigentlichen UDF "GaliNeo_UDF_GetProfileElement" nutzen:

CREATE FUNCTION dbo.GaliNeo_UDF_GetProfileElement
(
@fieldName AS NVARCHAR(100),
@fields AS NVARCHAR(4000),
@values AS NVARCHAR(4000)
)
RETURNS NVARCHAR(4000)
AS
BEGIN

  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

DECLARE @fieldNameToken AS NVARCHAR(20)
DECLARE @fieldNameStart AS INTEGER, @valueStart AS INTEGER, @valueLength AS INTEGER

SET @fieldNameStart = CHARINDEX(@fieldName + ':S',@Fields,0)

IF @fieldNameStart = 0 RETURN NULL
SET @fieldNameStart = @fieldNameStart + LEN(@fieldName) + 3

SET @fieldNameToken = SUBSTRING(@Fields,@fieldNameStart,LEN(@Fields)-@fieldNameStart)

SET @valueStart = dbo.GaliNeo_UDF_GetElement(1,@fieldNameToken,':')
SET @valueLength = dbo.GaliNeo_UDF_GetElement(2,@fieldNameToken,':')

IF @valueLength = 0 RETURN ''

RETURN SUBSTRING(@values, @valueStart+1, @valueLength)
END

Aus einer SQL Query kann jetzt diese Funktion wie folgt genutzt werden:
SELECT dbo.GaliNeo_UDF_GetProfileElement('PostalCode',PropertyNames,PropertyValuesString) FROM aspnet_Profile

So, das tat doch mal wieder fast nicht weh und bei 10.000 Profilen ist es von der Performance noch in Ordnung. Mal schauen wie es sich verhält, wenn man etwas mehr Daten in er DB hat.

 

Pingbacks and trackbacks (7)+

Kommentar schreiben