ORM - Create object with associations
One object's associated with many others:
Example: one Post
is part of开发者_如何学JAVA one Blog
, has a list of relations with Tags
, and many other things.....
Then I've one web form with dropdown boxes, each one filled from a custom query to retrieve only the Id and Name of that object, I am not getting ALL the object because it can have big size values (don't ask me why, but it can happen) and also because I don't need the other attributes to build the drop down box.
Now when I try to create this new Post
I need to do something like this:
Post post = new Post();
post.Blog = blog;
.....
Before ORM I could use SQL queries to create the object and pass only the Id of the blog, but now I need to pass the blog object. This means I'll need to retrieve it from the DB just to create the post, and this post also need tags objects and other things. I think this is an unnecessary operation. Why do I need to get all the other objects to create something else ?
There is a similar question here but without accepted answer.
I also will not cache the objects from the drop down boxes for the reasons I explained before.
I would like to create this post
passing only the Id
of the blog
. Is there any way to do this?
.
Note: using NHibernate but I think this is general ORM question.
You can use projection classes. Retrieving only the information you need and not the complete DB record.
One example:
HqlBasedQuery query = new HqlBasedQuery(typeof(Post),
@"
SELECT tags.Id, tags.Name
FROM Post post
INNER JOIN post.Tags tags
WHERE post.Id = ?
ORDER BY tags.Name
", postId);
var results = from object[] summary in (ArrayList)ActiveRecordMediator.ExecuteQuery(query)
select new YourProjectionClass
{
Id = (int)summary[0],
Name= (string)summary[1],
};
return results.ToList<YourProjectionClass>();
In ORMs, you can do just as you want :
create the Post using only a blog partially filled.
This is very ordinary code:
Post post = new Post();
post.setBlog(new Blog(123));
If used many times, there are obvious way to reduce this code. I leave this to you as an exercice ;-)
Note that it triggers other concerns. For example, when you deal with a Blog, it is fully initialized?
Right: if the ORM supports lazy fetching (hibernate does), sess.load(class, id) does not actually generate any SQL query but returns an uninialized proxy.
For Hibernate (not NHibernate, but it should be similar) I believe you can usually use HQL queries as follows to load objects:
select id from Blog where ...
You can load that into a Blog object and it'll work transparently. If you then access any of the properties that you didn't load, it'll trigger a query for the rest of its contents (or a LazyInitializationException, if you pass the object outside the scope of its session).
Collections and associations are usually also lazily loaded. The situation for simple parameter types is a bit more complicated, and I don't think there's an easy way to do it. If you find yourself mapping huge chunks of data's (i.e. CLOBs or BLOBs) you'll probably want to cheat a bit and map it using an association.
In any case, just because you've got the ORM framework doing the converting for you, doesn't mean you're excused from all the little details on how to load objects. In fact, getting the data access layer right is one of the toughest challenges. Especially when working with a legacy database that doesn't quite fit Hibernate's keep it simple principles.
精彩评论