2009-11-15 3 views
4

Je commence avec nHibernate et j'ai un exemple simple que je ne peux pas travailler comme je le voudrais.nhibernate 2 linq eager load

J'ai deux objets de modèle (Blog et Posts) et je voudrais les charger tous dans une seule requête pour un scénario. Je veux un chargement paresseux dans d'autres cas.

Je pensais naïvement que je pouvais écrire quelque chose comme ceci:

var blogs = session.Linq<Blog>().Expand("Posts"); 

Mais cela va me donner un exemple de blog pour chaque poste plutôt que d'ajouter des messages sur le blog. Je sais que je fais quelque chose de stupide. Quelqu'un peut-il s'il vous plaît préciser ce que c'est? Est-ce que j'ai besoin de relier les entités post et blog dans ma requête linq?

code

et Mappages:

public class Blog 
{ 
    public Blog() 
    { 
     Posts = new HashSet<Post>(); 
    } 
    public virtual long Identifier { get; set; } 
    public virtual string Name { get; set; } 
    public virtual ICollection<Post> Posts { get; set; } 
    public virtual Post AddPost(Post post) 
    { 
     post.Blog = this; 
     Posts.Add(post); 
     return post; 
    } 
} 


public class Post 
{ 
    public virtual long Identifier { get; set; } 
    public virtual string Name { get; set; } 
    public virtual Blog Blog { get; set; } 
} 

<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="nhibEx" namespace="nhibEx"> 
    <class name="Blog" lazy="true"> 
    <id name="Identifier"> 
     <generator class="native" /> 
    </id> 
    <property name="Name" not-null="true" length="100"/> 
    <set name="Posts" inverse="true" cascade="save-update" lazy="true"> 
     <key column="BlogIdentifier" foreign-key="fk_Post_Blog"/> 
     <one-to-many class="Post"/> 
    </set> 
    </class> 
</hibernate-mapping> 

<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="nhibEx" namespace="nhibEx"> 
    <class name="Post" lazy="true"> 
    <id name="Identifier"> 
     <generator class="native" /> 
    </id> 
    <property name="Name" not-null="true" length="255"/> 
    <many-to-one name="Blog" column="BlogIdentifier" class="Blog" /> 
    </class> 
</hibernate-mapping> 

Répondre

1

Distinct est ce que vous avez besoin ...

Edit: Quand il ne fonctionne pas: faire le distincte après la tolist. Je ne sais pas pourquoi NHibernate charge le même nombre d'objets que le nombre d'enregistrements de base de données retournés et ne fait pas la distinction automatiquement. Ce problème/cette fonctionnalité n'est pas spécifique à Linq, mais se produit également lorsque vous utilisez des critères ou hql.

session.Linq<Blog>().Expand("Posts").ToList().Distinct(); 

Parfois, il peut être plus efficace pour exécuter 2 requêtes (séparées, ou en utilisant MultiQuery/futur) que d'exécuter une requête avec une jointure externe gauche.

+0

Merci Paco et Alexey. Tu as raison, ça fait l'affaire. Je vais poster sur l'autre forum pour essayer de comprendre pourquoi il se comporte de cette façon. – LostSilver

-3

Nous avons exactement le même problème. Il me semble que linq est toujours en mode chargement ardent. Donc vous n'avez pas besoin de faire exapnd. Cependant c'est très mauvais. Avez-vous essayé de contacter les gars de HN dans leur groupe google?

+0

Linq n'est pas toujours en mode de chargement avide. – Paco

4

Après la recherche d'autres forums (peut-être que je aurais dû faire cela correctement d'abord!) J'utilise cette solution:

var blogs = session.Linq<Blog>(); 
blogs.QueryOptions.RegisterCustomAction(
criteria => criteria.SetResultTransformer(new DistinctRootEntityResultTransformer())); 
var results = blogs.Expand("Posts"); 

Je ne voulais pas utiliser Distinct que je voulais retourner IQueryable

Semble fonctionner. J'ai juste besoin de connaître la théorie :)

http://nhforge.org/wikis/howtonh/get-unique-results-from-joined-queries.aspx

+0

Merci d'avoir posté cette réponse – Paco

+2

Ceci n'est pas une solution: elle retournera moins de résultats si vous utilisez LIMIT x, y et supprime les doublons du côté du code. –