2011-07-21 4 views
4

J'ai eu des problèmes en utilisant C#, nhibernate et link. Dans l'exemple ci-dessous, je fais un SELECT dans le BrandTable, mais je n'ai besoin que des colonnes "Name" et "Id". Mais il fait toujours un select avec toutes les colonnes de la table. En utilisant EntityFramework, le même code ci-dessous génère un select avec seulement deux colonnes.Sélection de seulement quelques colonnes d'une table

Comment faire cela dans nhibernate?

using (ISession session = MyConnection.GetCurrentSession()) 
     { 
      var brands = from b in session.QueryOver<BrandTable>().List() 
           orderby b.Name 
           select new Brand {Id = b.id, Name = b.Name}; 

      return brands.ToList(); 
     } 
+0

Vous commandez et appliquez une projection en mémoire, c'est pourquoi cela ne fonctionne pas (la méthode .List() sélectionne tous les enregistrements – Vasea

Répondre

4

Ceci est un exemple en utilisant la projection:

List results = session.CreateCriteria<BrandTable>() 
.SetProjection(Projections.ProjectionList() 
    .Add(Projections.Id(), "Id") 
    .Add(Projections.Property("Name"), "Name") 
) 
.SetResultTransformer(Transformers.AliasToBean<BrandTable>()); // edit - don't forget the result transformer! 
.List(); 

ici un exemple en utilisant QueryOver:

NHibernate QueryOver select entity and aggregates

[modifier] aussi, il y a actuellement un bug lors de la mise en cache icriteria projections. (si vous essayez de mettre en cache la requête, vous obtenez une exception) https://nhibernate.jira.com/browse/NH-1090 [/ modifier]


messages Releted:

NHibernate Criteria: howto exclude certain mapped properties/collections?

Only retrieve specific columns when using Critera queries?

LINQ-NHibernate - Selecting only a few fields (including a Collection) for a complex object


rendre vos requêtes réusiner-safe (pas de « cordes magiques »), vous pouvez mettre en œuvre quelque chose comme ceci:

public static class ObjectExtensions 
{ 
    public static string NameOf<T>(this T target, Expression<Func<T, object>> propertyExpression) 
    { 
     MemberExpression body = null; 
     if (propertyExpression.Body is UnaryExpression) 
     { 
      var unary = propertyExpression.Body as UnaryExpression; 
      if (unary.Operand is MemberExpression) 
       body = unary.Operand as MemberExpression; 
     } 
     else if (propertyExpression.Body is MemberExpression) 
     { 
      body = propertyExpression.Body as MemberExpression; 
     } 
     if (body == null) 
      throw new ArgumentException("'propertyExpression' should be a member expression"); 

     // Extract the right part (after "=>") 
     var vmExpression = body.Expression as ConstantExpression; 

     // Extract the name of the property 
     return body.Member.Name; 
    } 

} 

en utilisant comme ceci:

MyEntity entity = null; // don't need a 'valid' instance. 
string propName = entity.NameOf(x => x.SomePropertyName); 
+0

Ce deuxième exemple ne fonctionne pas, il envoie toutes les colonnes à interroger –

+0

Le deuxième exemple doesn Ne fonctionne pas car il filtre la collection en mémoire – Vasea

+0

J'ai mis à jour le post! thx! – danyolgiax

1

Vous pouvez aussi le faire avec QueryOver dans NH. Ci-dessous est tirée de http://nhforge.org/blogs/nhibernate/archive/2009/12/17/queryover-in-nh-3-0.aspx

Projections

projections simples des propriétés du type racine peuvent être ajoutés en utilisant la méthode .Choisir qui peut prendre plusieurs arguments d'expression Lambda:

IList selection = 
    session.QueryOver<Cat>() 
     .Select(
      c => c.Name, 
      c => c.Age) 
     .List<object[]>(); 

Parce que cette requête ne plus renvoie un chat, le type de retour doit être explicitement spécifié. Si une seule propriété est projetée, le type de retour peut être spécifié à l'aide:

IList<int> ages = 
    session.QueryOver<Cat>() 
     .Select(c => c.Age) 
     .List<int>(); 

Il y a plusieurs autres exemples de la façon d'utiliser les projections dans le lien ci-dessus.

6

Vous ne pouvez pas utiliser les requêtes avec QueryOver, car ce n'est pas un fournisseur Linq. Dans votre exemple, vous sélectionnez tous les enregistrements, puis utilisez LINQ to Objects. Ajoutez le NHibernate.espace de noms LINQ à votre fichier et réécrire la requête comme

from b in session.Query<BrandTable>() 
orderby b.Name 
select new Brand {Id = b.id, Name = b.Name}; 
0

Vous pouvez sélectionner une colonne pour un domaine en utilisant l'étape suivante:

  1. Créer une petite classe avec les champs que vous veut: Exemple:

private class LeadInformation 
    { 
      public string Id { get; set; } 
      public DateTime AdmissionDate { get; set; } 
    } 

  1. Interrogez la entité de domaine où voulez-vous pour en extraire les informations

IQueryable leads = 
       repository.Query() 
       .Where(x => x.AdmissionRepUserObj.ID.ToString() == filter.UserId 
        ).Select(lead => new LeadInformation 
        {AdmissionDate = lead.DateApplied.Value, 
        Id = lead.ID.ToString()}); 

Dans le chef d'exemple est l'entité que nous voulons extraire les informations. Observez que la destination est du même type que la classe cible LeadInformation. Renvoie une liste interrogeable de la classe cible LeadInformation avec seulement deux colonnes de la classe de domaine source.

Questions connexes