开发者

Can entities be attached to an ISession that weren't previously attached?

开发者 https://www.devze.com 2023-02-03 05:12 出处:网络
I\'m playing around with NHibernate 3.0. So far things are pretty cool. I\'m trying to attach an entity that wasn\'t detached previously:

I'm playing around with NHibernate 3.0. So far things are pretty cool. I'm trying to attach an entity that wasn't detached previously:

var post = new Post(){ Id = 2 };
session.Update(post); // Thought this would work but it doesn't.
post.Title = "New Title After Update";
session.Flush();

What I'm trying to write is the following:

var post = new Post(){ Id = 2 };
session.Attach(post);
post.Title = "New Title After Update";
session.Flush(); // Sql should be something like: UPDATE Post SET Title='New Title After Update' WHERE Id=2

Is this possible so that only Title gets updated? This is currently possible in EntityFramework. I'd like to not have to load Post from the database when I just need to update a few properties. Also, I'm trying to avoid a method call that would create the object... since it's moving away from an object oriented approach in my opinion.

EDIT: I know about using transactions, I just used Flush() to make the code simple. Ok so I think we're sort of getting on the right track for what I'm trying to achieve. I'd like to be able to create an entity with a known Id using the constructor, like I have in the 2nd code block above. I don't want to have to make a call to Get<T> or Load<T> since it feels rather wrong constructing objects like this that already exist in the 开发者_开发技巧database. For example, in Entity Framework I can write the 2nd code example and it will "just work". It only updates the Title property.


You can session.Save() or session.SaveOrUpdate()

update

Okay, I think I see now what you are trying to do. You are trying to update a single property on a Post that was previously persisted, not a new Post, and to do that you're instantiating a new Post and giving it the Id of one in the database.

I'm not sure what you mean when you say you're trying to avoid a method call that would create the object, but the way to do this with NHibernate is this:

var post = session.Load<Post>(2);
post.Title = "New Title";
session.SaveOrUpdate(post);

In general, you should not be calling Flush() on your sessions.

The important thing to note here is the use of session.Load. Calling Load with an id in and of itself does not load the entity from the database. The entity's property values will only be loaded when/if you access them.

Of course, in this scenario, I believe that NHibernate will load the properties for the Post, (but not collections unless you've specified an eager fetch mode), and that makes sense (frankly, I don't understand why EF would not load the entity). What if the setter for your Title property does something important, like check it against the existing title, validate the title's length, check your credentials, or update another property? Simply sending an UPDATE to the database isn't sufficient.


It's possible to only update changed properties by setting dynamic-update in the mapping. However, as far as I know, it is not possible (without reverting to SQL) to perform an update without retrieving the object from the database at some point.


Use the Merge method. You have to create a new instance variable to accept the attached entity = nhibernate will not do anything else with your detached instance.

        var post = new Post(){ Id = 2 };
        post.Title = "New Title After Update";
        // Must create a new instance to hold final attached entity
        var attachedPost = session.Merge(post);
        session.Update(attachedPost);
        session.Flush();
        // Use attachedPost after this if still needed as in session entity

That covers the "attach" functionality you are looking for, but I don't see how you are going to be able to only update the one property. if the object instance has not been populated from the database, the properties will be different. Dynamic mapping will not solve this - NHibernate sees the properties as "updated" to a bunch of nulls, empty strings.

Gotta say, you are creating a new instance but what you are actually doing is updating an existing instance. You are working directly with IDs not objects. And you are setting a single property and now have an instance potentially hanging around and doing more things but it has not enforced any invariants and may in fact bear no resemblence to the real deal other than the id property...

It all feels pretty anti-object oriented to me personally.

0

精彩评论

暂无评论...
验证码 换一张
取 消