Biggle's Blog

Web- und Software Development

by Mario Binder

Connectionstring ermitteln – The simplest way

Der wohl einfachste Weg einen Connectionstring zu ermitteln und dabei noch den String verifizieren, kann man durch folgende Verfahrensweise. (Voraussetzung Visual Studio & SQL Server Management Studio (SSMS)

Man legt sich an einem Ort seiner Wahl ein File mit der Extension *.udl an z.B. conn.udl und klickt dieses File doppelt. Hier kann man nun den Server und die Datenbank auswählen, die man im Connectionstring benötigt. Unter Provider noch den richtigen DB-Provider festlegen und zum Schluss mit OK bestätigen.

Voila, öffnent man sein *.udl file nun mit dem Editor, findet man dort seinen Connnectionstring : )

1
2
3
[oledb]
; Everything after this line is an OLE DB initstring
Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=tempdb;Data Source=SX-PC\sqlexpress

by Mario Binder

Stored Procedure mit skalaren Rückgabewert im Entity Framework

Will man Stored Procedures über das Entity Framework aufrufen, kann man das – wenn man denn ein EntitySet erwartet – recht einfach. Erwartet man aber eine skalare Variable (Int32, String, Guid…) weiter als Response, gibt es leider ein bekanntes Problem, dass dafür kein Code generiert wird.

Um dennoch eine solche Procedure verwenden zu können, müssen einige Einträge in dem Model von Hand getätigt und im Code muss eine eigene EntityConnection implementiert werden, die für den StoredProcedure-Aufruf eine temporäre Verbindung aufbaut. Um das zu verdeutlichen, hier meine Herangehensweise in einem Testprojekt.

In der Datenbank erstelle ich mir vorerst eine Stored Procedure namens GetPersonenId. Diese Procedure erwartet zwei Parameter, zum einen eine Id, und zum anderen einen boolschen Wert. Was genau in der SP passieren soll, ist für dieses Beispiel nicht relevant.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
USE [TestDB2]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[GetPersonenId]
	@Root uniqueidentifier ,
	@Rekursiv bit
AS
BEGIN
	SET NOCOUNT ON;
 
	If @Rekursiv = 0
	BEGIN
		select PersonenId
		from Personen
		where ChildId = @Root
	End
 
	Else
	Begin
		-- rekursive abfrage...
	End
END

Nun füge ich meinem Projekt ein ADO.NET Entity Data Model hinzu und wähle aus meine Datenbankverbindung meine Datenbank aus.

Im kommenden Dialog wähle ich hier unter den “Gespeicherten Prozeduren” meine SP aus.

Das nun erstellte Model schliesse ich und öffne das auch gleich wieder mit den integrierten XML-Editor, dazu ein Rechtsklick auf das Model im Projektmappen-Explorer und auf “Öffnen mit…” Hier wähle ich dann den XML Editor zum öffnen des Modells.

Hier findet man den generierten Code kommentiert mit den jeweiligen Bereichen (SSDL, CSDL, C-S mapping). Im Knoten edmx:StorageModels (SSDL content)  sollte bereits, eine vom EF definierte Funktion existieren, die den Namen der Procedure trägt.

1
2
3
4
<Function Name="GetPersonenId" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="false" ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo">
  <Parameter Name="Root" Type="uniqueidentifier" Mode="In" />
  <Parameter Name="Rekursiv" Type="bit" Mode="In" />
</Function>

Die kann so belassen werden. Im Knoten edmx:ConceptualModels (CSDL content) fügen wir ein FunktionImport Knoten hinzu, der den Rückgabetypen und die Parameter wie diese in der StoredProcedure definiert wurden. Wenn der Knoten EntityContainer kein schliessendes Tag hat sondern /> endet, muss dieser so geändert werden.

1
2
3
4
<FunctionImport Name="GetPersonenId" ReturnType="Collection(Guid)">
  <Parameter Name="Root" Type="Guid" Mode="In" />
  <Parameter Name="Rekursiv" Type="Boolean" Mode="In" />
</FunctionImport>

Im Knoten edmx:Mappings (C-S mapping content) ergänzen wir im Knoten EntityContainerMapping den Knoten FunctionImportMapping. Der kommende FunctionName im Code  ist der im Schema definierte Namespace plus der Name von der SP. Auch hier wichtig, wenn der Knoten EntityContainerMapping kein schliessendes Tag hat sondern /> endet, muss dieser so geändert werden.

1
<FunctionImportMapping FunctionImportName="GetPersonenId" FunctionName="PersonenModel.Store.GetPersonenId" />

Das edmx-File kann nun gespeichert und geschlossen werden und wir wechseln in die Klasse wo wir die Methode bauen möchten, die die Prozedur  aufruft. Jetzt verweisen wir noch auf System.Configuration um den ConfigurationManager für die Übergabe des ConnectionStrings aus der App.Config. Der Connectionstring kann aber auch direkt in die Variable connection geschrieben werden…

Hier nun der Code, in den Kommentare werden die einzelnen Zeilen kommentiert.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public static IEnumerable<Guid> ReadPersonenIdStruktur(Guid root, bool recursive)
{
    //Liste instanziieren
    var personen = new List<Guid>();
 
    //connectionstrring aus der app.config holen
    string connection = ConfigurationManager.ConnectionStrings["PersonenEntities"].ConnectionString;
 
    //context verwenden
    using (var conn = new EntityConnection(connection))
    {
        try
        {
            //connection oeffnen
            conn.Open();
 
            //EntityCommand instanzieren
            EntityCommand cmd = conn.CreateCommand();
 
            /* der comandtext setzt sich aus den entities-namen der
             * bei der Erstellung des Models festgelegt wurde
             * plus den Namen der Stored Procedur                     *
             */
            cmd.CommandText = "PersonenEntities.GetPersonenId";
 
            //commandtype festlegen
            cmd.CommandType = CommandType.StoredProcedure;
 
            //die parameter die erwartet werden von der sp dem Kommando hinzufuegen
            cmd.Parameters.AddWithValue("Root", root);
            cmd.Parameters.AddWithValue("Rekursiv", recursive);
 
            //ausfuehren
            var result = cmd.ExecuteReader(CommandBehavior.SequentialAccess);
 
            //ergebnisse in die liste schreiben
            while (result.Read())
            {
                personen.Add((Guid)result.GetValue(0));
            }
        }
        catch (Exception ex)
        {
            //Fehlerbehandlung
        }
        finally
        {
            //connection schliessen und wegschmeissen
            conn.Close();
            conn.Dispose();
        }
    }
    return personen;
}

Wenn noch Fragen offen sind, versuche ich zu helfen. Ansonsten wie immer,

viel Spass beim entwickeln : )


by Mario Binder

SQL Joins – CheatSheet

Einen kleinen Überblick über die Arten von SQL Joins bekommst du mit folgenden CheatSheet.

by Mario Binder

SQL ManagementStudio 2008 unter XP

Ich wollte eigentlich nur die SSMS Tools installieren um mir ein Insert Statement aus einem bestehenden Datensatz zu generieren. SSMS möchte aber gerne mindestens die 2008er Version von SQL MangementStudio. Nun denn, nun sind doch ein paar mehr Installationen notwendig…

Möchte man das SQL MangementStudio 2008 unter XP verwenden, muss man etwas Zeit mitbringen und so einiges an Programmen installieren.

Das wäre dann zuerst PowerShell und der WindowsInstaller 4.5. Das SQL MangementStudio hätte auch gerne das Service Pack 1 für Visual Studio 2008. Wichtig dabei ist hier, das man auch die Sprache des ServiePacks wählt, wie auch das Visual Studio installiert ist. Und zu guter Letzt nun, darf man auch die SSMS Tools installieren.

btw, Das SQL ManagementStudio 2008 rennt auch parallel mit der 2005er Version.


by Mario Binder

Verteilte Datenbankabfragen

Wenn man ein Ergebniss von mehreren Tabellen aus verschiedenen Datenbanken selektieren möchte, kann man das über ein UNION bewerkstelligen.

Die Anzahl der zu selektierenden Spalten muss immer gleich sein. Man kann auch verschiedene Spalten abfragen, diese müssen aber immmer vom selben Datentyp sein. Gegebenfalls muss man diese dann in den entsprechenden Typen casten.

Example


SELECT lastname, firstname FROM db1.contactTable
UNION
SELECT lastname, firstname FROM db2.otherTable


by Mario Binder

Nützliche mathematische SQL-Funktionen

Im Folgenden eine Übersicht von mathematischen SQL Funktionen

Select  Funktion

Liefert …

ABS(x)

den Absolutwert von x

ACOS(x)

den ArkuskoSinus von x

ASIN(x)

den ArkusSinus von x

ATAN(x, y)

den ArkusTangens von xund y

CEIL(x)

die kleinste Ganzzahl, die größer oder gleich x ist (Rückgabetyp entspricht einem BigInt)

COS(x)

den Kosinus von x

COT(x)

den Kotangens von x

EXP(x)

Exponential –> e hoch x

FLOOR(x)

die größte Ganzahl, die kleiner oder gleich x ist

FORMAT(x, y)

von x einen formatierten String  auf y Nachkommastellen

LN(x)

den natürlichen Logarithmus von x

LOG(x, y)

den natürlichen Logarithmus von x  zur Basis y

MOD(x, y)

den Rest von x geteilt durch y (Modulo)

PI()

den Wert von PI

POWER(x, y)

den  Wert von x hoch y

RADIANS(x)

den Wert von x in Grad nach Rad

RAND()

eine zufällige Fließkommazahl

ROUND(x)

den Wert von x gerundet auf die nächste Zahl

ROUND(x, y)

den Wert von x gerundet auf y Nachkommastellen

SIGN(x)

1 wenn x == positiv,  0 oder -1 wenn x == negativ (Link)

SIN(x)

den Sinus von x

SQRT(x)

die Quadratwurzel von x

TAN(x)

den Tangens von x

TRUNCATE(x, y)

den Wert von x auf y Nachkommastellen abgeschnitten

Als Bild downloaden