I'm st开发者_运维技巧arting out with nHibernate and have a simple example that I cannot get working as I'd like.
I have two model objects (Blog and Posts) and I would like to load them all in a single query for one scenario. I want lazy loading in other cases.
I naively thought that I could write something like this:
var blogs = session.Linq<Blog>().Expand("Posts");
But this will give me an instance of blog for every post rather than adding the posts to the blog.
I know I'm doing something stupid. Can someone please point out what it is? Is it that I need to relate the post and blog entities in my linq query?
Code and Mappings:
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>
After searching other forums (perhaps I should of done this properly first!) I'm using this solution:
var blogs = session.Linq<Blog>();
blogs.QueryOptions.RegisterCustomAction(
criteria => criteria.SetResultTransformer(new DistinctRootEntityResultTransformer()));
var results = blogs.Expand("Posts");
I didn't want to use Distinct as I wanted to return IQueryable
Seems to work. I just need to know the theory :)
http://nhforge.org/wikis/howtonh/get-unique-results-from-joined-queries.aspx
Distinct is what you need...
Edit: When it doesn't work: do the distinct after the tolist. I don't know why NHibernate loads the same number of objects as the number of database records returned and doesn't do the distinct automatically. This issue/feature is not Linq specific, but will also happen when you use criteria or hql.
session.Linq<Blog>().Expand("Posts").ToList().Distinct();
Sometimes it can be more efficient to execute 2 queries (seperate, or using multiquery/future) than executing one query with a left outer join.
We have just the same problem. It seems to me that linq is always in eager loading mode. So you don't need to do exapnd. However it is very bad. Have you tried to contact HN guys in their google group?
精彩评论