For example, I have Dog and Cat classes:

Dog dog = new Dog(); dog.Age = 4;

Cat cat = new Cat(); cat.Age = 3;

And I want to save only dog entity.

How can I save it separately? Session.Persist() will save cat entity too.

I need it because I want to develop class based on 'Repository pattern' with Save(T entity) method, so I don't need to save ALL entities in session.

This thread was imported from our support forum. The original discussion may contain more detailed answer. Original topic by VoimiX.

asked May 15 '10 at 16:48

Editor's gravatar image

Editor
46156156157


One Answer:

Short answer is: there is no way to do this: DO is designed to automatically track and persist all the entities, so you can't make it persist just one.

Now - some details:

1. There is Session.Pin(...) method allowing you to temporarily prevent any attempts of DO4 to save a particular entity.

But its purpose is to prevent this for relatively short amount of time inside a transaction (~ like pinning in .NET). Pinning also implies:

  • You won't try to complete a transaction with pinned entities. So you must dispose all IDisposables returned by Session.Pin(...) before commit or rollback, otherwise an exception will be thrown.

  • Any entity referencing newly created pinned entity is considered as pinned as well (because there is no way to persist the reference in this case).

2. Repository pattern doesn't imply automatic tracking and persistence. It implies these tasks are handled manually.

Moreover, repository pattern with Save() instead of SaveAll() normally implies you care about correct saving order by your own - i.e. if entity can't be saved because it points to unsaved entity, there will be an error, and it's your problem to establish correct saving order. If there is a cycle (A.B = B; B.C = C; C.A = A), it's your problem to detect and break it (by temporarily breaking one of the references, persisting the graph and then restoring it back and persisting the changes again).

If these problems are handled automatically, Save() method doesn't provide such fine-granted control over saving sequence that you expect (because ORM might persist more then you expect just because there are some references), so IMHO it becomes meaningless.

Of course, if there is SaveAll(), there is no such issue. But let's take e.g. NHibernate as an example: when you run a query, it anyway executes Session.Flush (~= SaveAll) to ensure all the changes are already in the database, and executed query will reflect this. This behavior is controllable (i.e. you can turn it off), but default mode is used in almost any practical case.

Now let's take a look at DO4: since it also automatically loads the data it needs, it might need to invoke Session.Persist (~= SaveAll) automatically in many manuy cases - e.g. when EntitySet part is loaded or entity is going to be removed and DO looks up for references pointing to it. If flushing isn't done in such case, it would be quite hard to find a bug: we imply persistent model can be combined from types developed by completely different teams. In such case it's virtually impossible to ensure that EntityByTeamA is saved, when QueryByTeamBUsingDataFromEntityByTeamA is executed - without automatic flushes, of course. If there is just Save(), a case like this turns into a complete hell.

So that's why we implemented automatic saving, and that's why Session.Pin(...) must be used as rare as possible, and for as short period as it's possible. Probably the closest analogy is garbage collection: it provides lots of benefits, but requires you to pass it some part of control over the process. So a question like "Where is Save method?" can be rephrased as "Where is delete statement in .NET?".

You must also note that automatic saving provides some really noticeable benefits:

3. If you're looking for solution allowing you to temporarily cache the changes through multiple transactions (or completely offline), and flush them by an explicit command, see DisconnectedState.

Link: http://goo.gl/rpxW

answered May 15 '10 at 19:52

Alex%20Yakunin's gravatar image

Alex Yakunin
29714412

Your answer
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!
toggle preview

powered by OSQA