Zur Zeit wird gefiltert nach: February 1
Filter zurücksetzen

Sharepoint - Der Unterschied der Versionsbezeichnung zwischen Frontend und Datenhaltung

Bei einem grösseren Migrationsprojekt hatte ich eine interessante Aufgabenstellung im Bezug auf die Versionsbezeichnung von Dokumenten. Im Frontend und im Export-XML (Manifest.xml) werden diese in für Benutzer lesbarer Form als 0.1, 0.2 bzw. 1.0 angezeigt. Intern ist die Version dagegen als 1, 2 bzw. 512 abgelegt.

In einem ersten Schritt habe ich eine Metadatenschicht aufgebaut. Die Gründe hierfür sind:

  • Übersicht des zu erwarteten Aufwands bzw. Fortschritts
  • Intensive Tests
  • KPI's und Auswertungen für das Management
  • Analyse der Datenqualität

Die aufbereiteten Metadaten enthalten die sogenannte interne Version der Datenhaltung. Die Versionsbezeichnung der Sharepoint Content Deployment API enthält hingegen die Bezeichnung, wie sie der Benutzer sieht.

Tabellarisch gesehen sieht die Gegenüberstellung so aus:

Frontendversion

Interne Version

0.1

1

0.2

2

1.0

512

1.1

513

2.0

1024

Der Aufbau dieser Versionen folgt einer Regel:

  • Hauptversionen steigen in 512-Schritten
  • Nebenversion fortlaufend

Mit dieser Information war ich in der Lage, das Ganze in einer Hilfsklasse zu packen, die in der Lage ist, die Konvertierung in die interne bzw. Frontendversion vorzunehmen.

Codebeispiel Konverter:


    public class SharepointVersionConverter
    {
        const int MainVersionIdentifier = 512;

        public static string GetSharepointVersionStringFromInternalVersion(int version)
        {
            return String.Format("{0}.{1}", version / MainVersionIdentifier, version % MainVersionIdentifier);
        }

        public static int GetSharepointInternalVersionFromString(string version)
        {
            if (String.IsNullOrEmpty(version))
                throw new ArgumentException("version is null or empty.", "version");

            var split = version.Split('.');

            if (split.Length != 2)
                throw new ArgumentException("Wrong version string");

            return Int32.Parse(split[0]) * MainVersionIdentifier + Int32.Parse(split[1]);
        }
    }

So habe ich jetzt die Möglichkeit, die interne Version aus den Metadaten mit der Frontendversion zu vergleichen, um so die Metadatenschicht aktualisieren zu können.

Weitere Informationen zum Thema:

CLR Funktion für den SQL Server erstellen

Lange habe ich auf die Gelegenheit und einen Anwendungsfall gewartet, um eine CLR Funktion für den SQL Server schreiben zu können. Für ein Migrationsprojekt habe ich nun einen Einsatzzweck gefunden. ;-)

Hauptgrund dafür ist, dass eine Anwendung abgelöst werden soll, die ihre Business Logik in C# implementiert hat. Der Code ist nach den gängigen Clean Code Regeln erstellt, das ist sofort ersichtlich, die Datenhaltung ist dafür sehr kreativ.

Da der imperative Code die Logik aus den Daten zusammenstellt, habe ich mich für den Ansatz entschieden, eine CLR Funktion für den SQL Server zu schreiben. Würde ich diese Logik in T-SQL abbilden, wäre die Performanz und Verständlichkeit grausam. Da eine grosse Datenmenge migriert werden muss, ist ein Ansatz notwendig, der einerseits performant läuft, anderseits wenig Aufwand verursacht.

So habe ich nun die Möglichkeit eine SQL Server Eigenschaft zu nutzen, die seit der Version 2005 existiert.

Gehen wir nun der Reihe nach vor. Zuerst wird ein Projekt vom Typ Klassenbibliothek angelegt. Anschliessend lege ich einen Schlüssel an, damit die Assembly auch signiert werden kann. Die Implementierung ist recht einfach. Es werden die Referenzen:

  • System.Data.Sql
  • System.Data.SqlTypes
  • Microsoft.SqlServer.Server

benötigt. Das Grundgerüst der Klasse hat folgenden Aufbau:


using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.Sql;
using System.Data.SqlTypes;
using System.Linq;
using System.Text;
using Microsoft.SqlServer.Server;

namespace Firma.Projekt.TVFStringConvert
{
    public class StringConvertTable
    {
        [SqlFunction(FillRowMethodName = "FillRow")]
        public static IEnumerable Inititalize(string tags)
        {
            return ParseString(tags);
        }

        public static void FillRow(Object obj, out SqlInt32 keyId, out SqlInt32 valueId)
        {
            if (obj == null)
                SqlContext.Pipe.Send("The obj to create a tupel is null.");

            Tag tag = obj as Tag;
            keyId = tag.ParentId;
            valueId = tag.Id;
        }       

        public static ICollection<Tag> ParseString(string tagString)
        {
            if (tagString != null)
            {
                return ExternalLib.Convert(tagString);
            }

            return new List<Tag>(0);
        }       
    }
}

Einstiegspunkt ist in meinem Beispiel die Methode Initialize. Diese wird mit dem Attribute SqlFunction versehen. Mit diesem wird festgelegt, dass die Methode FillRow ein Tupel für die Verwendung in T-SQL aufbereitet. Der erste Parameter enthält die Informationen dafür. Die eigentliche Logik beziehe ich dabei aus einer anderen Bibliothek und ist nicht Bestandteil des Codebeispiels.

Nachdem diese CLR Funktion erstellt ist, muss diese auf dem SQL-Server registriert werden. Dies erfolgt in mehreren Schritten. Zuerst wird die Assembly registriert und anschliessend eine Funktion erstellt, welche auf die Logik in der Assembly zeigt. Nachfolgendes Beispiel zeigt den Ablauf:


USE TestDatabase
GO

-- Für Permission Set External_Access und Unsafe
-- Bad Practice, besser die DLL mit einem richtigen Zertifikat signieren 
-- ALTER DATABASE TestDatabase SET TRUSTWORTHY ON

IF EXISTS (SELECT name FROM sysobjects WHERE name = 'StringConvertTable')
   DROP FUNCTION StringConvertTable
GO

IF EXISTS (SELECT name FROM sys.assemblies WHERE name = 'TVFStringConvert')
   DROP ASSEMBLY [TVFStringConvert]
GO

CREATE ASSEMBLY [TVFStringConvert] 
FROM 'C:\projects\ Firma.Projekt.TVFStringConvert\Firma.Projekt.TVFStringConvert.dll'
WITH PERMISSION_SET = UNSAFE --SAFE 
GO

CREATE FUNCTION StringConvertTable(@tags nvarchar(max)) 
RETURNS TABLE (
   keyId int,
   valueId int
)
AS EXTERNAL NAME TVFStringConvert.[Firma.Projekt.TVFStringConvert.StringConvertTable].[Inititalize]
GO

-- Test (Weiterverwendung mit CROSS APPLY)
SELECT * FROM StringConvertTable('kreative Datenlogik')
GO

Falls die Fehlermeldung

Execution of user code in the .NET Framework is disabled. Enable "clr enabled" configuration option.

erscheint, muss diese Option aktiviert werden.

Mit folgendem Befehl ist dies möglich:


-- Servereinstellungen
EXEC sp_configure 'clr enabled', 1
GO
RECONFIGURE
GO

Ich habe nun einen praktikablen und pragmatischen Weg, der auf die Situation abgestimmt mit akzeptabler Performanz die Daten (kreative Datenlogik) in auswertbarer Form für die Migration bereitstellt.

Mein nächster Schritt besteht darin das Ganze mit parallelisierter Ausführung weiter zu beschleunigen.

Weitere Informationen zum Thema:

15.02.2012
20:38

Wieder gefunden

Wenn Du ein Schiff bauen willst, dann trommle nicht Männer zusammen um Holz zu beschaffen, Aufgaben zu vergeben und die Arbeit einzuteilen, sondern lehre die Männer die Sehnsucht nach dem weiten, endlosen Meer.

Antoine de Saint-Exupery

Translate this page

Kategorien

  • [-].NET Development (215)
  • [-]Datenbank (26)
  • HTML (1)
  • Konfiguration (12)
  • Mind Map (10)
  • Off-topic (9)
  • Open Source (3)
  • Qualität (7)
  • Sharepoint (6)
  • Sicherheit (2)

Archiv

Social Bookmarking

Bookmark bei: Mr. Wong Bookmark bei: Webnews Bookmark bei: Icio Bookmark bei: Oneview Bookmark bei: Linkarena Bookmark bei: Favoriten Bookmark bei: Seekxl Bookmark bei: Favit Bookmark bei: Social Bookmarking Tool Bookmark bei: Power Oldie Bookmark bei: Bookmarks.cc Bookmark bei: Newskick Bookmark bei: Newsider Bookmark bei: Linksilo Bookmark bei: Readster Bookmark bei: Folkd Bookmark bei: Yigg Bookmark bei: Digg Bookmark bei: Del.icio.us Bookmark bei: Reddit Bookmark bei: Simpy Bookmark bei: StumbleUpon Bookmark bei: Slashdot Bookmark bei: Netscape Bookmark bei: Furl Bookmark bei: Yahoo Bookmark bei: Spurl Bookmark bei: Google Bookmark bei: Blinklist Bookmark bei: Blogmarks Bookmark bei: Diigo Bookmark bei: Technorati Bookmark bei: Newsvine Bookmark bei: Blinkbits Bookmark bei: Ma.Gnolia Bookmark bei: Smarking Bookmark bei: Netvouz Information