-
Notifications
You must be signed in to change notification settings - Fork 935
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix #1419 - ISession.IsDirty() shouldn't throw exception for transient many-to-one object in a session #1420
Conversation
src/NHibernate/Type/ManyToOneType.cs
Outdated
return true; | ||
} | ||
|
||
if (ForeignKeys.IsTransientFast(GetAssociatedEntityName(), current, session) == true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to use IsTransientSlow
, otherwise the bug will still be there for entities having an assigned id already assigned or having an unsaved-value
set as undefined
. IsTransientSlow
hits the db only if IsTransientFast
was not able of answering, which occurs in aforementioned cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to have a test for this case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@fredericDelaporte, the GetEntityIdentifierIfNotUnsaved
calls IsTransientFast
as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, what will happen in case of an entity with assigned ID - the "IsDirty" method will not fail, but it will return false
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to use IsTransientSlow, otherwise the bug will still be there
Are you sure? I simply reused check that lead to exception:
nhibernate-core/src/NHibernate/Engine/ForeignKeys.cs
Lines 250 to 265 in a6f97d0
if (IsTransientFast(entityName, entity, session).GetValueOrDefault()) | |
{ | |
/***********************************************/ | |
// TODO NH verify the behavior of NH607 test | |
// these lines are only to pass test NH607 during PersistenceContext porting | |
// i'm not secure that NH607 is a test for a right behavior | |
EntityEntry entry = session.PersistenceContext.GetEntry(entity); | |
if (entry != null) | |
return entry.Id; | |
// the check was put here to have les possible impact | |
/**********************************************/ | |
entityName = entityName ?? session.GuessEntityName(entity); | |
string entityString = entity.ToString(); | |
throw new TransientObjectException( | |
string.Format("object references an unsaved transient instance - save the transient instance before flushing or set cascade action for the property to something that would make it autosave. Type: {0}, Entity: {1}", entityName, entityString)); |
So in your case exception won't be thrown by GetIdentifier(current, session);
method. And result will be given to identifierType.IsDirty
method.
the "IsDirty" method will not fail, but it will return false
Why false? What IsDirty returns depends on identifierType.IsDirty
call. And from my understanding it should work fine - we will simply check if identifier value is changed. And if it's new object - it should definitely change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just in case I made a quick test with assigned id and it works OK. Should I squash it in to test commit? Or separate commit is OK?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, better add it to test commit. You may first add it as a "fixup! Test case for GH1419 (ISession.IsDirty() failed for transient many-to-one" commit and later squash it if you prefer.
Well, already added, never mind, can still be squashed later.
Ok, what will happen in case of an entity with assigned ID - the "IsDirty" method will not fail, but it will return false.
I believe IsTransientFast
yields null
instead in that case, but @bahusoid test seems to show I were wrong in assuming the whole case would fail. Adding tests for assigned id and unsaved-value "undefined" is definitely the way to go. (Maybe can we disregard the undefined
case, using that option looks a bit like calling for troubles, I do not know why it even exist.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was checking with Assigned Guids. Not sure why it works with integers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hazzik I changed int to Guid in my test and it still works...
Note: My first attempt with assigned id was also failing until I realized that I forgot to map new property in parent object )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe I had the same problem ;)
Added new test as separate commit. Let me know if it needs to be rebased and squashed instead. |
Thanks. Nice work |
Fixes #1419