Laden...

NHibernate: Fetching im Repository

Erstellt von mctimotheus vor 11 Jahren Letzter Beitrag vor 11 Jahren 1.496 Views
M
mctimotheus Themenstarter:in
179 Beiträge seit 2008
vor 11 Jahren
NHibernate: Fetching im Repository

verwendetes Datenbanksystem: SQL Server 2008 R2 // NHibernate

Hallo Community,

ich komme bei einem Problem einfach nicht weiter. Ich stelle für die Entitäten meiner Anwendung jeweils ein Repository zur Verfügung. In diesem Repository möchte ich eine Methode zur Verfügung stellen, die alle Entitäten ausließt und der ich als Parameter übergeben kann welche Childnodes mitgeladen werden sollen.

Hierzu habe ich mir folgende Methode überlegt:


public IEnumerable<User> FindAll<TRelated>(Expression<Func<User, IEnumerable<TRelated>>> fetchExpression) {
    return session.Query<User>().Fetch(fetchExpression);
}

Soweit, so gut. Nun bin ich aber nicht in der Lage diese Methode aufzurufen. Ich würde gerne wie folgt die Methode aufrufen:


var user = repository.FindAll(x => new[] { x.Orders, x.Roles });

Das geht aber leider nicht, da Orders und Roles nicht vom gleichen Typ sind. Hat jemand eine Idee oder sieht meinen Denkfehler?

Wer nicht wagt .. der nicht gewinnt .. !

106 Beiträge seit 2011
vor 11 Jahren

Hallo mctimotheus,

wenn ich das richtig verstanden habe, dann willst du bestimmte Childs je nach bedarf Eager laden oder? Ich würde für jeden Bedarf eine einzelne Methode zur verfügung stellen.
Z.B.:


public IEnumerable<User> FindAllWithOrdersAndRoles() {}
public IEnumerable<User> FindAllWithOrders() {}
public IEnumerable<User> FindAllWithRoles() {}

Btw. das ist nicht wirklich eine NHibernate bezogene Frage, da die Session die du nutzt auch keine ISession zu sein scheint. Zumindest hat die ISession in NHibernate keine "Query()" funktion.

MfG
Rabban

M
mctimotheus Themenstarter:in
179 Beiträge seit 2008
vor 11 Jahren

Wenn du den Namespace NHibernate.Linq einbindest hast du auch die Query() Methode in deiner Session zur Verfügung. Dann kannst du wie in Entity Framework auch übliche LINQ-Abfragen absetzen.

Die Variante für jeden Fall des Nachladens eine eigene Methode zu schreiben halte ich für etwas ungeeignet, da man ja auch das Nachladen der Childs kombinieren können soll. Also Beispielsweise so: Lade mir alle User mit den dazugehörigen Rollen und Aufträgen aber nicht das IT-Equiment der User.

Wer nicht wagt .. der nicht gewinnt .. !

2.187 Beiträge seit 2005
vor 11 Jahren

Hallo mctimotheus,

also Typensicher geht es nur wie Rabban es vorgeschlagen hat (so weit ich sehe).
Wenn man aber auf die Typensicherheit verzichtet, kann man mit Reflection hier etwas machen.
Dazu muss man die Properties übergeben und nicht deren inhalt (so wie in deinem Code).

  1. Als strings (einfach aber unschön).
  2. Als Expressions (etwas schöner, aber trotz Intellisense und so weiter nicht typensicher).

Gruß
Juy Juka


IUser x = null;
IEnumerable<IUser> userList = null;
userList = repository.FindAll(()=>x.Orders, ()=>x.Roles);
userList = repository.FindAll();
userList = repository.FindAll(()=>x.Roles);


  ...

  using System;
  using System.Linq.Expressions;
  using System.Reflection;  

  ...

    public virtual void IEnumerable<IUser> FindAll(params Expression<Func<object>>[] properties)
    {
      ...
      foreach(Expression<Func<object>> zwi in properties)
      {
        PropertyInfo property = Helper.PropertyOf(zwi);
        // jetzt wie auch immer das Property "eager fetch" markieren/machen/laden/...
        ...
      }
      ...
    }

  ...

  internal static class Helper
  {
    public static PropertyInfo PropertyOf(Expression<Func<object>> property)
    {
      PropertyInfo propertyInfo = null;
      MemberExpression memberExpression = property == null ? null : property.Body as MemberExpression;
      UnaryExpression unaryExpression = property == null ? null : property.Body as UnaryExpression;
      if (memberExpression != null)
      {
        propertyInfo = memberExpression.Member as PropertyInfo;
      }
      else if (unaryExpression != null)
      {
        propertyInfo = ((MemberExpression)(unaryExpression).Operand).Member as PropertyInfo;
      }

      if (propertyInfo == null)
      {
        throw new ArgumentException(Properties.Resources.LambdaFehler);
      }
      return propertyInfo;
    }
  }
}

106 Beiträge seit 2011
vor 11 Jahren

Sehr interessanter Ansatz JuyJuka, ich werds mal bei gelegenheit ausprobieren.
Btw. Die Url aus deiner Signatur geht nicht^^

MfG
Rabban