Archiv

Posts Tagged ‘Persistenz’

Präsentation “Introducing RavenDB” bei der @dnugbe

22. Oktober 2013 Kommentare aus

Als Vorbereitung für meine Präsentation an der SoftShake 2013 durfte ich am 16. Oktober einen Testlauf bei der .Net User Group Bern machen. Mit über 20 interessierten Teilnehmern hatte ich dafür ein ausgezeichnetes Publikum. Die Fragen und Rückmeldungen zeigten mir wo ich mich noch verbessern kann und welche Teile schon bereit sind.

Da etliche Zuhörer sich RavenDB nun einmal genauer anschauen wollen habe ich die Folien wiederum auf Speakerdeck veröffentlicht:

Folien zu Introducing RavenDB auf SpeakerDeck

Die Beispiele die ich vorgestellt habe sind allesamt aus meinen Beiträgen auf Improve & Repeat, dem englischsprachige Ableger meines Blogs. Dort gibt es nicht nur den Code sondern auch eine Erklärung der man ohne Vorwissen folgen kann.

Auch nach der Präsentation gibt es noch einiges was ich über RavenDB zu berichten habe. Diese Beiträge werden in den nächsten Wochen erscheinen und können über den RSS-Feed abonniert werden.

Als Abschluss möchte ich mich nochmals bei den Teilnehmern bedanken. Ohne interessierte Zuhörer sind solche Testläufe nicht möglich. Merci!

 
PS: Wer die Einführung lieber in Deutsch hat findet hier im Blog mit “RavenDB: Eine Einführung” einen passenden Beitrag.

 

Nachtrag 31. 10. 2013

Die Folien der Soft-Shake Präsentation sind nun ebenfalls auf Speakerdeck abgelegt.
 

Schlagworte: , ,

EF 5: Modelle übersichtlicher gestalten

17. März 2013 1 Kommentar

Ob man nun “Model-First” oder “DB-First” folgt, bei Entity Framework steht man schnell einmal vor einem Problem: Das Datenmodell verliert an Übersichtlichkeit.

Die oft verwendeten Beispiele mit wenigen Tabellen und Verbindungen sehen im Designer von Visual Studio prima aus. Hat man aber ein komplexeres Modell steht man bald einmal vor so einer Ansicht:

Unübersichtliches Modell

Auch wenn man sehr viel Zeit aufwendet um die Entitäten hin und her zu ziehen, so bleibt das Modell doch unübersichtlich. Verwendet man Entity Framework 5 und Visual Studio 2012 gibt es aber 2 Hilfsmittel die einem bei der Organisation helfen können.

 

Farben

Mit Hilfe von Farben kann man thematisch zusammenhängende Bereiche hervorheben. Dazu klickt man im Designer die gewünschte Tabelle (oder mittels der Hilfe von CTRL mehrere) an und wählt in den Properties die entsprechende Füllfarbe (Fill Color):

Farbe auswählen

Die Farben haben einzig im Designer eine Bedeutung und beeinflussen das Modell nicht. Mit wenig Aufwand sieht das Diagramm dann so aus:

Farbiges Modell

 

Diagramme

Für grosse Modelle sind die Farben zwar ein Anfang, doch ist man damit noch nicht am Ziel. Neu kann man das Modell aber in verschiedene Diagramme aufteilen. Die entsprechende Funktion findet sich im Model Browser unter Diagramme:

Diagramm hinzufügen

Die gewünschten Entitäten können nun auf dieses neue Diagramm gezogen werden. Man muss dies aber nicht für jede Entität einzeln machen. Über das Kontextmenü auf einer Entität kann man mit “Include Related” alle verbundenen Entitäten auf einmal einfügen lassen.

Die so erzeugten Diagramme behandeln nur noch den Ausschnitt aus dem Modell den man genauer betrachten möchte:

Zusätzliches Diagramm

Beim Löschen von Entitäten aus dem Diagramm muss man aufpassen. Mittels “Delete from Model” wird die Entität aus dem Modell gelöscht und ist danach über den DB-Kontext nicht mehr abrufbar. In der Regel will man stattdessen die Funktion “Remove from Diagram” nutzen. So wird nur das Diagramm angepasst und das Modell bleibt unverändert.

 

Fazit

Mit Hilfe von Farben und zusätzlichen Diagrammen kann man Ordnung in sein DB-Modell bekommen. So kann man auch grössere Datenbanken in Entity Framework benutzen ohne die Übersicht zu verlieren.

Schlagworte: ,

NHibernate: Resultate Transformieren mit DistinctRootEntityResultTransformer

30. August 2011 5 Kommentare

Ich hatte vor einiger Zeit ein recht mühsames Problem: Obwohl ich Objekte nach deren Id (Primärschlüssel) aus der DB geholt habe sind diese mehrmals in meinem Resultat erschienen. Wie so oft war der Fehler eigentlich eine Kleinigkeit, doch solange man gar nicht auf die Idee kommt an der richtigen Stelle danach zu suchen steht man vor einem grossen Mysterium.

 
Ausgangslage
Für das stark vereinfachte Beispiel nutze ich die 3 Klassen Order, OrderItem und Product. Die Objekte dienen nur zum ablegen der Daten und verfügen über keine Geschäftslogik. Das Feld Id ist jeweils der Primärschlüssel der gleichnamigen Tabellen. OrderItem ist sowohl mit Product wie auch mit Order verbunden.

 
Ein Test schlägt fehl
Mit dem untenstehenden Test werden die nötigen Objekte angelegt und danach versucht die Order anhand der Id zu laden.

[TestMethod]
public void ReproduceTheProblem()
{
    using (ISession session = PersistenceManager.OpenSession())
    {
        // Arrange
        Order order = new Order { Number = "000001" };
        AddDataToOrder(session, order);

        // Act
        List<Order> orders = GetOrderById(session, order.Id);

        // Assert
        Assert.AreEqual(1, orders.Count);
        // ==> Assert.AreEqual failed. Expected:<1>. Actual:<2>.
    }
}

private static List<Order> GetOrderById(ISession session, int id)
{
    var result = session.CreateCriteria(typeof(Order))
                        .Add(Expression.Eq("Id", id))
                        .List<Order>();

    return result.ToList();
}

Das Resultat in diesem Test ist allerdings nicht wie erwartet eine 1, sondern eine 2. Schaut man sich das generierte SQL-Query an kann man auch erkennen was das Problem ist:

SELECT 
	this_.Id as Id1_1_, 
	this_.Number as Number1_1_, 
	items2_.OrderId as OrderId3_, 
	items2_.Id as Id3_, 
	items2_.Id as Id2_0_, 
	items2_.OrderId as OrderId2_0_, 
	items2_.Quantity as Quantity2_0_, 
	items2_.ProductId as ProductId2_0_ 
FROM dbo.[Order] this_ 
left outer join dbo.OrderItem items2_ on this_.Id=items2_.OrderId 
WHERE this_.Id = 3;

Hier wird nicht einfach nur ein SELECT gemacht, sondern das Resultat wird noch mit einem JOIN verknüpft. Meine Erwartung war das nur eine Zeile mit den Daten für das von mir gewünschte Objekt zurück geliefert wird. Durch den JOIN werden nun aber auch alle dazugehörigen OrderItems geladen:

 
Ursache
Der JOIN wurde von NHibernate nicht einfach aus lauter Freude gemacht. Die dafür nötige Anweisung stand so im Mapping:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="NHDistinct" namespace="NHDistinct.Model">
  <class name="Order" table="`Order`" schema="dbo">
    <id name="Id">
      <generator class="identity" />
    </id>
    <property name="Number" />
    <bag name="Items" cascade="all-delete-orphan" inverse="true" fetch="join">
      <key column="OrderId"/>
      <one-to-many class="NHDistinct.Model.OrderItem"/>
    </bag>
  </class>
</hibernate-mapping>

Diese explizite Schreibweise hat den gleichen Effekt als würde man die Funktion zum holen der Daten so umschreiben:

private static List<Order> GetOrderById(ISession session, int id)
{
    var result = session.CreateCriteria(typeof(Order))
                        .Add(Expression.Eq("Id", id))
                        .SetFetchMode("Items", FetchMode.Join)
                        .List<Order>();

    return result.ToList();
}

Obwohl das Ergebnis gleich ist, sieht man so auf den ersten Blick das ein wenig mehr Daten kommen werden als man als Nutzer der Methode vermuten würde. (Klare Methodennamen wären wie so oft eine grosse Hilfe gewesen).

 
Lösung
Das Mapping durfte nicht verändert werden, da das so erzwungene Verhalten fürs gesamte Projekt gesehen Sinn machte. Auch war ein erzwungenes nicht laden der OrderItems für die weitere Verarbeitung ungünstig. Nach einigem Suchen wurde die Funktion schliesslich um eine Zeile erweitert:

private static List<Order> GetOrderByIdFixed(ISession session, int id)
{
    var result = session.CreateCriteria(typeof(Order))
                        .Add(Expression.Eq("Id", id))
                        .SetFetchMode("Items", FetchMode.Join)
    /*  NEU: ===>  */   .SetResultTransformer(new DistinctRootEntityResultTransformer()) 
                        .List<Order>();

    return result.ToList();
}

DistinctRootEntityResultTransformer nimmt das Resultat der Abfrage und transformiert dieses wieder in die Root Entitäten. NHibernate packt auch ohne diese Zeile die OrderItems ins Order-Objekt, so aber merkt es dass es nur einen Order gibt und liefert entsprechend auch nur noch eines zurück.

 
Fazit
Wenn man mit OR-Mappern arbeitet sollte man bei der Entwicklung immer einen Blick auf die generierten Abfragen werfen. Meistens macht es das Richtige aber für den kleinen Spezialfall den man nun gerade braucht gibt es halt ab und zu ein klein wenig Nacharbeit. Was wieder mal zeigt: Trotz OR-Mappern sollte man als Entwickler doch ein wenig Ahnung von SQL haben.

 
Danksagung
Ich möchte hier noch Patrick Weibel danken. Ich durfte für den Blogpost seine Klasse PersistenceManager.cs aus dem ORM-Vortrag bei der .Net User Group Bern verwenden. Die Klasse zusammen mit den zahlreichen Mappings zum Nachschauen hat mir ermöglicht ein Minimal-Beispiel zusammen zu stellen, das man fürs selber experimentieren auf BitBucket herunterladen kann.

Schlagworte:

Buch-Rezension zu “Programming Entity Framework“

Programming Entity Framework“ von Julia Lerman erschien im August 2010 in der 2. Ausgabe bei O’Reilly. Diese Ausgabe wurde für Entity Framework 4 komplett überarbeitet. Will man mit EF 4 arbeiten sollte man also unbedingt schauen das man diese Ausgabe kauft.

 

Ich bin jeweils ein wenig skeptisch wenn ich ein Buch mit über 700 Seiten sehe. Zu oft reicht das Wissen der Autoren nur für rund 500 Seiten und der Rest ist dann eine mehr oder weniger gekonnte Wiederholung. Dies ist hier aber definitiv nicht der Fall!

Julia Lerman gilt zu Recht als DIE Expertin zu Entity Framework ausserhalb von Microsoft. Die Teile zu EF sind sehr fundiert und liefern auch einen sehr guten Einblick in die Entstehungsgeschichte des neusten OR-Mappers von Microsoft.

 
Mehr als nur Entity Framework
Das Buch behandelt alle Teile die man zum Verstehen von Entity Framework braucht. Es beginnt mit dem Entity Data Model und den Abfragemöglichkeiten mit LINQ to Entities oder Entity SQL. Es folgen Tipps und Trick wie man mit dem EDM Designer arbeitet und wo man ihn umgehen muss. Ob man Self-Tracking Entities oder POCOs nutzen will, man findet für beide Ansätze ausführliche Anleitungen. Kapitel zu Transaktionen oder dem Mappen von Stored Procedures fehlen ebenso wenig wie die Einbindung von realitätsnahen (und damit komplexen) DB-Schemas in Entity Framework. Das Buch lässt diesbezüglich keine Wünsche offen.

Am meisten beeindruckte mich aber wie der konkrete Einsatz von EF erklärt wird. Ob man Windows Forms, WPF, WCF oder ASP.Net nutzt – für alle diese Technologien gibt es mindestens ein Kapitel das einem zeigt worauf man achten muss. Man ist so in der Lage EF in seinem eigenen Projekt zu nutzen ohne noch viele zusätzliche Informationen suchen zu müssen.

Mit seinem Umfang an Informationen ist „Programming Entity Framework“ auch sehr gut als Nachschlagewerk geeignet. Ein ausführlicher und gut gepflegter Index hilft beim Finden der passenden Stelle.

 
Kleine Kritikpunkte
Es gibt aber auch bei dem Buch noch einige wenige Verbesserungsmöglichkeiten. Die meisten Bilder im Kapitel 14 sind um 1-2 Nummern verschoben. Dies stört beim Lesen doch recht stark, da man vergeblich versucht das gerade erklärte auf dem Bild zu finden. Auch die Strukturierung könnte man bei einer 3. Ausgabe wohl noch ein wenig optimieren. Etliche der Verweise auf eine spätere Erklärung des Themas würden so entfallen.

 
Fazit
Wer sich mit Entity Framework beschäftigen will sollte sich dieses Buch unbedingt kaufen. Vor allem die Kapitel die auf die Nutzung von EF mit den einzelnen Microsoft Technologien (wie WPF, WCF, Windows Forms oder ASP.Net) eingehen sind eine sehr grosse Hilfe bei der täglichen Arbeit.

 
Zum Buch
Programming Entity Framework“ von Julia Lerman, 2010 O’Reilly, ISBN 978-0-596-80726-9, 912 Seiten, Englisch

Schlagworte: , ,

SQL WHERE Bedingung erzeugen mit dem Composite Pattern

7. Januar 2011 6 Kommentare

In “Refactoring to Patterns” bin ich auf das Refactoring “Replace One/Many Distinctions with composite” gestossen. Dort wird ein Beispiel gezeigt bei dem verschiedene Kriterien (Gleich, Und, Oder) zu einem Entscheidungsbaum kombiniert werden.

Als ich mir die Grafik mit all den AND und OR anschaute, entdeckte ich darin eine mögliche Lösung für ein Problem mit SQL Abfragen. Bei einem Projekt nutzen wir DTOs um Daten aus der Datenbank zu unserem GUI zu bringen. Die Abfragemöglichkeit ist bisher auf AND limitiert, was aber für unseren Einsatzzweck ausreicht. Für Verknüpfungen mit OR und jede beliebige Mischung davon fehlt uns bisher eine elegante Lösung.

 
Ein Spike wird gestartet
Bei Extreme Programming gibt es sogenannte Spikes. Dies sind minimalisierte Projekte um genau ein Problem zu untersuchen. Ich finde diesen Ansatz recht praktisch und habe daher einen Spike gestartet um die Möglichkeiten des Composite Patterns auszutesten.

Für die Umsetzung braucht es ein Interface, dass von allen Klassen der WHERE Bedingung implementiert werden muss. Ich entschied mit für IWhereClause und die Methode GetClause():

interface IWhereClause
{
    string GetClause();
}

Am häufigsten wird wohl auf die Gleichheit von Werten geprüft werden müssen. Die Klasse EqualsClause soll dies ermöglichen:

class EqualsClause : IWhereClause
{
    private readonly string _leftSide;
    private readonly string _rightSide;

    public EqualsClause(string leftSide, string rightSide)
    {
        _leftSide = leftSide;
        _rightSide = rightSide;
    }

    public string GetClause()
    {
        return String.Format(" ({0} = '{1}') ", _leftSide, _rightSide);
    }
}

Erzeugt man ein Objekt mit den Parametern “x” und “done” wird dieses Ergebnis von GetClause() geliefert:

(x = ‘done’)

Soweit alles andere als spektakulär, aber dennoch ein wichtiger Grundstein. Der nächste Schritt ist die Verknüpfung mittels AND. Dazu dient die Klasse AndClause:

class AndClause : IWhereClause
{
    private readonly IWhereClause _leftSide;
    private readonly IWhereClause _rightSide;

    public AndClause(IWhereClause leftSide, IWhereClause rightSide)
    {
        _leftSide = leftSide;
        _rightSide = rightSide;
    }

    public string GetClause()
    {
        return String.Format(" ({0} AND {1}) ", _leftSide.GetClause(), _rightSide.GetClause());
    }
}

Dieser Klasse kann man nun Objekte die das Interface IWhereClause implementieren übergeben. Bis hier her erfüllen diese Bedingung EqualsClause und auch AndClause. So können nun mehrere AndClause Objekte ineinander verschachtelt werden.

 
Die WHERE Bedingung erzeugen
Analog der beiden Klassen habe ich mir noch NotEqualsClause und OrClause erzeugt. Diese variieren durch die veränderte Bedingung (OR statt AND und <> statt =) in GetClause(). Mit diesen 4 Klassen kann ich nun Werte auf Gleichheit oder Ungleichheit prüfen und die Ergebnisse mit AND oder OR verknüpfen. Es wird nun Zeit diese Möglichkeiten im Code zu nutzen.

Ziel ist es, so einen Entscheidungsbaum in C# zu erzeugen:

Die erzeugten Klassen werden dazu nun miteinander verschachtelt:

static void Main()
{
    // basic nodes with equals / not equals
    IWhereClause creationIsDone = new EqualsClause("creation", "done");
    IWhereClause paymentIsOpen = new EqualsClause("payment", "open");
    IWhereClause stateNotShipped = new NotEqualsClause("state", "shipped");

    // composites of nodes with and / or
    IWhereClause createdAndnotPaid = new AndClause(creationIsDone, paymentIsOpen);
    IWhereClause waitForPaymentORnotShipped = new OrClause(createdAndnotPaid, stateNotShipped);

    // This could build the SQL statement to get all created Orders  
    // who wait for payment or shipping
    Console.WriteLine("SELECT * FROM orders \nWHERE " + waitForPaymentORnotShipped.GetClause());

    Console.ReadLine();
}

Die Ausgabe kombiniert alle Objekte und liefert die Abfrage um alle erzeugten aber nicht bezahlten Aufträge sowie diejenigen die noch nicht verschickt wurden auszugeben:

SELECT * FROM orders
WHERE ( ( (creation = ‘done’) AND (payment = ‘open’) ) OR (state <> ‘shipped’) )

 
Fazit
Mit dem Composite Pattern kann man relativ einfach die WHERE Bedingung erzeugen. Für einen produktiven Einsatz benötigt dieser Spike allerdings noch einige Umbauten und Erweiterungen (wie ein Equals für long). Als Grundlage für weitere Diskussionen wird er aber seinen Zweck erfüllen.

Wer selber noch ein wenig experimentieren will findet den Source Code auf BitBucket unter http://bitbucket.org/jgraber/spike-whereclause.

Schlagworte:
Follow

Erhalte jeden neuen Beitrag in deinen Posteingang.

Schließe dich 254 Followern an