Archiv

Archive for August 2011

USA 2011 – Sommerferien einmal XXL

31. August 2011 Kommentare aus

Im Juni und Juli genoss ich meine Sommerferien in den USA. Nach dem ich letztes Jahr die Ostküste besuchte wollte ich diesmal in 6 Wochen den Westen erkunden.

Da Dollar ihre Mietwagen nur für maximal 4 Wochen abgeben will teilte ich meine Reise in 3 Blöcke. Die ersten 4 Wochen wollte ich nutzen um mir die Westküste und die Nationalparks rund um den Grand Canyon anzuschauen. Weitere 10 Tage plante ich für Texas und die Great Plains ein. Zum Abschluss wollte ich noch einige autofreie Tage in New York verbringen. Neben den vielen Einkaufsmöglichkeiten sind die 6 Stunden Zeitdifferenz zur Schweiz auch eine gute Jetlag Prävention.

 

Route

 

Wie man der Karte entnehmen kann wurden die Distanzen dann doch noch ein wenig länger. Mit über 40 Grad im Schatten war es mir im Süden schnell zu heiss. So verblieb ich in Arizona und Utah nur kurz und fuhr zu den „Möchte-ich-sonst-auch-noch-sehen“-Zielen im Norden. Da ich sehr gut voran kam konnte ich auch noch einen Abstecher nach Kanada machen. Leider zeigte sich Whistler von seiner nassen Seite.

Auch beim Mount St. Helens hatte ich mit dem Wetter Pech. Vor lauter Nebel konnte ich vom Observatorium aus den Berg nicht sehen. Tags darauf war das Wetter wieder super und so fuhr ich von Portland aus halt noch einmal hin. Der Unterschied war frappant:

 

USA_2011__20_MountStHelens_04 USA_2011__20_MountStHelens_05

 

Die nächsten 2 Wochen blieb das Wetter so gut. Erst in Mobile (Alabama) gab es dann wieder ein richtiges Gewitter. Die Regenmenge die dabei innert kürzester Zeit fiel war erstaunlich. Strassen und Plätze verwandelten sich in Bäche und Seen. Für einmal war auch auf der Interstate kein Weiterkommen mehr möglich. Ein Vorteil aber hatte der Regen: Er kühlte die Luft auf angenehme 20 Grad. (So tiefe Temperaturen hatte ich bis zu meiner Rückkehr nicht mehr)

Abgesehen von diesen wenigen Regentagen und einem kleinen Sandsturm im Monument Valley hatte ich mit dem Wetter viel Glück. So richtig heiss wurde es im Süden erst als ich im Norden war. Die Überschwemmungen um den Mississippi waren schon deutlich zurückgegangen bis ich dort eintraf. Und die Tornados sah ich nur auf dem Weather Channel. Auch auf der Strasse gab es keine Zwischenfälle. Die rund 18‘000 km verliefen ohne irgendwelche Pannen oder Unfälle.

 

Nationalparks und Monumente


Spricht man von Nationalparks denken viele an den Grand Canyon oder an Yellowstone. Die beiden konnte ich mir natürlich nicht entgehen lassen. Aber auch der Arches N.P. mit seinen Bögen, der Bryce Canyon und der Crater Lake waren einen Besuch wert. Wer selber einmal hin will sollte einen Blick auf die Webseite des US National Park Service werfen. Ich fand die dort zusammengeführten Hintergrundinformationen und Karten äusserst nützlich.

USA_2011__04_GrandCanyon_13 USA_2011__14_YellowstoneNP_35 USA_2011__07_BryceCanyon_14 USA_2011__09_ArchesNP_12 USA_2011__08_MonumentValley_03 USA_2011__22_CraterLakeNP_04

Neben den Nationalparks gibt es auch noch die Nationalen Monumente. Diese sind von der Fläche her meist kleiner, aber oft ebenfalls äusserst sehenswert.

USA_2011__12_DevilsTower_07 USA_2011__11_MountRushmore_03

In Dallas besuchte ich unter anderem das Football Stadion der Dallas Cowboys. Dies ist zwar kein Nationales Monument, aber dennoch monumental. Das über 1 Mia $ teure Bauwerk ist nicht nur für Football-Fans einen Besuch wert. „In Texas ist alles Grösser“ gilt bei diesem Station für alles – auch die Monitore über dem Spielfeld mit einer Diagonale von 53 Meter…

USA_2011__27_DallasCowboys_02 USA_2011__27_DallasCowboys_17

 

Erholen in New York


Der letzte Teil meiner Reise führte mich nach New York. Mein Hotel (das Renaissance) war direkt am Times Square. Einen Schritt aus der Lobby raus und man war mitten im Getümmel – zentraler kann ein Hotel kaum liegen. Der Lärm hielt sich dank der guten Schallschutzfenster in Grenzen.

Wie erhofft konnte ich mich in New York noch ein wenig erholen. Was bei vielen wohl nur Kopfschütteln auslöst ist tatsächlich möglich. Der Central Park ist so riesig das man dort problemlos seine Ruhe finden kann. Wenn man die Touristenströme zeitlich ein wenig umgehen kann findet man auch auf dem Top of the Rock eine fast leere Aussichtsplattform.

USA_2011__37_NewYork_14

Mittlerweile ist auch der Wolkenkratzer One World Trade Center so hoch das man ihn von weitem sehen kann. In knapp einem Jahr wuchs das Gebäude um fast 50 Stockwerke. Die Geschwindigkeit ist in Zahlen schon unglaublich. Steht man aber davor und sieht den Unterschied bekommt man erst so richtig mit was dies bedeutet.

2010 2011

 

Wo einmal genug ist


Von all den vielen Orten und Sehenswürdigkeiten die ich auch meiner Reise besuchte gibt es eigentlich nur 2 die mich enttäuscht haben.

Vom Skywalk in Grand Canyon West hatte ich mir viel mehr erwartet. In der Doku von National Geographic sah dies so gross und toll aus. Der Skywalk ist aber sehr klein und man darf seine eigene Kamera nicht mitnehmen. Im Gegensatz zum Grand Canyon N.P. darf man auch nicht mit seinem Auto herum fahren. Man muss auf Busse warten deren Fahrplan dem Besucheransturm nicht gewachsen ist. Schlechte Organisation gepaart mit einem überrissenen Eintrittspreis gibt bei mir die Empfehlung den Skywalk auszulassen.

Das Johnson Space Center in Houston hat abgesehen von einer Saturn V und der Space Vehicle Mockup Facility nicht wirklich viel zu bieten. Der Rest ist ein Mix aus Spielplatz und Food-Court. Wer etwas über die NASA erfahren will geht besser nach Florida.

USA_2011__04_GrandCanyon_17 USA_2011__30_Houston_12

 

Weitere Fotos


Wer gerne noch mehr Fotos sehen möchte findet diese im Album USA 2011 auf Flickr.

Bis bald

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:
Folgen

Erhalte jeden neuen Beitrag in deinen Posteingang.

Schließe dich 296 Followern an