saveOrUpdate(Object) method of Hibernate - nhibernate

when i use saveOrUpdate(Object) method of Hibernate. How can I know that row is updated or new row added into table??? Return type of method saveOrUpdate(Object) is void, so am not able to find out the result after calling this method.
kindly help me.

As I understand from your question and comment lived. You could create an event listener and implement two Interfaces: IPreUpdateEventListener, IPreInsertEventListener
e.q.
public class AuditEventListener : IPreUpdateEventListener, IPreInsertEventListener
{
public bool OnPreUpdate(PreUpdateEvent #event)
{
//your stuff here
return false;
}
public bool OnPreInsert(PreInsertEvent #event)
{
//your stuff here
return false;
}
}
but I think this is ridiculous. using ORMs means that you do not care about persistence and all work is done the unitofwork. If you really need to insert and update just use Save() or Update() methods, in this way you will exactly know what operation is made.

If your object to be persisted is having identifier property set to 0(/id null) then it means it is a new object and will be inserted newly in db.
After it is inserted hibernate will then set the id value in identifier field.
If already the object has identifier property set then it means the object is already persisted and it can be updated
EDIT:Did you look at hibernate interceptors?May be this is useful.
example

Related

Mask properties from dirty check

I have a column in all my tables called LoggedInPersonID. To avoid cluttering mapping code, an Nhibernate Interceptor overrides OnFlushDirty and OnSave to assign the LoggedInPersonID property automatically.
If LoggedInPersonID is the only property changed, I consider the entity clean. At the moment Nhibernate (rightfully) considers the entity to be dirty.
Does any mapping construct exist to escape a property from Nhibernate's dirty check, while still including the column in any inserts/updates?
Alternatively, I have considered implementing the IPreUdateEventListener interface and use the OnPreUpdate event to check whether the only difference between OldState and State is in the property LoggedInPersonID, and cancel the update if that is the case. Would that be a valid approach?
I think if you already change the property in OnSave, the dirty check will come after, and finally OnFlushDirty will occur, when it is already decided. At least if you (unnecessarily) call Save() or SaveOrUpdate() on your object, although it is not a newly created one.
Simplier case
I would rather try to avoid setting LoggedInPersonID if the entity is not dirty. I am not comfortable with cancelling the update from IPreUdateEventListener: a lot of other processing still occurs, like second level cache updating, and other PostUpdate processing.
OnFlushDirty xml doc states:
Called when an object is detected to be dirty, during a flush.
So this means NHibernate considers your object to be dirty even before you have set its LoggedInPersonID.
You should probably check that in your interceptor with a conditional break-point to stop only on your entity type having troubles, and check if there is already some other changes between currentState and previousState before your code affects its LoggedInPersonID.
Maybe have you by example some other logic elsewhere which has already set LoggedInPersonID.
Harder case
But checking NHibernate code, it could be a bit muddier. It looks to me like OnflushDirty could be called on entities which might be dirty. (And maybe this "might be dirty" is caused by what I had suspected in my answer on your previous question.)
I such case, you should do your own dirty check inside your interceptor. You may do the dirty check in your OnFlushDirty, but then NHibernate will still do its own, causing the dirty check to be done twice. To avoid dirty checking twice each entity, you need then do your first idea: evicting LoggedInPersonID from the dirty check if this is the only dirty property.
NHibernate dirty check implementation is not trivial. Better reuse it than coding your own dirty check. But this need adding some code to your interceptor. (Done with the help of this blog on NHibernate.info.)
using NHibernate;
using NHibernate.Type;
using NHibernate.Proxy;
...
public class LoggedInPersonIDInterceptor : EmptyInterceptor
{
...
// your previous code handling the setting of LoggedInPersonID
...
private ISession _session;
public override void SetSession(ISession session)
{
_session = session;
}
public override int[] FindDirty(object entity, object id,
object[] currentState, object[] previousState,
string[] propertyNames, IType[] types)
{
var sessionImpl = _session.GetSessionImplementation();
var persistenceContext = sessionImpl.PersistenceContext;
var entry = persistenceContext.GetEntry(entity);
if (entry == null)
{
// The blog post try to handle proxy case but that part looks
// buggy to me. If you do not need to handle proxies, just let
// default implementation do the job by returning null here.
return null;
}
var persister = sessionImpl.Factory.GetEntityPersister(entry.EntityName);
var dirtyPropertiesIndexes = persister.FindDirty(currentState,
previousState, entity, sessionImpl);
// Probable superfluous null check...
if (dirtyPropertiesIndexes == null || dirtyPropertiesIndexes.Length != 1)
{
return dirtyPropertiesIndexes;
}
if (propertyNames[dirtyPropertiesIndexes[0]] == "LoggedInPersonID")
{
// return empty array for telling that nothing has changed
return new int[] {};
}
return dirtyPropertiesIndexes;
}
}
Side note : I have seen in your other question revisions your were testing on propertyNames[i].ToLower() == "loggedinpersonid". If you need that, I generally prefer do that this way : StringComparer.OrdinalIgnoreCase.Equals(propertyNames[i], "LoggedInPersonID"). This avoid messing up while manually lower-casing the property name.
Other solution
Maybe this other way I found later would be easier.

Deserializing IEnumerable with private backing field in RavenDb

I've been modeling a domain for a couple of days now and not been thinking at all at persistance but instead focusing on domain logic. Now I'm ready to persist my domain objects, some of which contains IEnumerable of child entities. Using RavenDb, the persistance is 'easy', but when loading my objects back again, all of the IEnumerables are empty.
I've realized this is because they don't have any property setters at all, but instead uses a list as a backing field. The user of the domain aggregate root can add child entities through a public method and not directly on the collection.
private readonly List<VeryImportantPart> _veryImportantParts;
public IEnumerable<VeryImportantPart> VeryImportantParts { get { return _veryImportantParts; } }
And the method for adding, nothing fancy...
public void AddVeryImportantPart(VeryImportantPart part)
{
// some logic...
_veryImportantParts.Add(part);
}
I can fix this by adding a private/protected setter on all my IEnumerables with backing fields but it looks... well... not super sexy.
private List<VeryImportantPart> _veryImportantParts;
public IEnumerable<VeryImportantPart> VeryImportantParts
{
get { return _veryImportantParts; }
protected set { _veryImportantParts = value.ToList(); }
}
Now the RavenDb json serializer will populate my objects on load again, but I'm curious if there isn't a cleaner way of doing this?
I've been fiddeling with the JsonContractResolver but haven't found a solution yet...
I think I've found the root cause of this issue and it's probably due to the fact that many of my entities were created using:
protected MyClass(Guid id, string name, string description) : this()
{ .... }
public static MyClass Create(string name, string description)
{
return new MyClass(Guid.NewGuid(), name, description);
}
When deserializing, RavenDb/Json.net couldn't rebuild my entities in a proper way...
Changing to using a public constructor made all the difference.
Do you need to keep a private backing field? Often an automatic property will do.
public IList<VeryImportantPart> VeryImportantParts { get; protected set; }
When doing so, you may want to initialize your list in the constructor:
VeryImportantParts = new List<VeryImportantPart>();
This is optional, of course, but it allows you to create a new class and start adding to the list right away, before it is persisted. When Raven deserializes a class, it will use the setter to overwrite the default blank list, so this just helps with the first store.
You certainly won't be able to use a readonly field, as it couldn't be replaced during deserialization. It might be possible to write a contract resolver or converter that fills an existing list rather than creating a new one, but that seems like a rather complex solution.
Using an automatic property can add clarity to your code anyway - as it is less confusing whether to use the field or the property.

Property which should be a readonly db-field (Fluent NHibernate Automapping)

Im using the Fluent NHibernate together with the automapping functionality. Now im lookin' for something like a configuration, setting, custom attribute - whatever - to declare an entity property as "ReadOnlyFromDb"
In the MsSql database im using a computed column in one of my tables where a value is calculated depending on some other values of the specific data row. Now I have declared this column in the entity class as
public virtual int STATUS { get; private set; }
On getting the specific data of the table everything works fine. The property STATUS is filled correct with the specific value in the datatable.
The problem occures when i try to SaveUpdate() the specific object.
I always get the exception
A computed column cannot be the target of an INSERT or UPDATE statement
Which is correct for my understanding - and its how it was supposed to be ;)!
Basically im looking for a configuration, setting, custom attribute - whatever - to say
Hey Fluent NHibernate - get the specific property propertyName but do not insert / update the property propertyName
Is there something like that? Or does a workaround exists for this case?
I've searched the fluent nhibernate wiki but have not found a smilliar case.
I hope that someone has already faced and solved this problem!
Here is the code snippet how I create the session (maybe it helps):
public static ISessionFactory GetNHibernateSession()
{
if (nhibernateSession != null)
return nhibernateSession;
if (ConfigurationManager.AppSettings[msSqlConnectionString] == null || ConfigurationManager.AppSettings[msSqlConnectionString] == String.Empty)
throw new NullReferenceException(String.Format("AppSetting '{0}' must not be null!", msSqlConnectionString));
//nhibernateSession = Fluently.Configure().Database(MsSqlConfiguration.MsSql2005.ConnectionString(ConfigurationManager.AppSettings[msSqlConnectionString]))
// .Mappings(m => m.AutoMappings.Add(AutoMap.AssemblyOf<T_ABWEICHUNGEN>().IgnoreBase<BaseClass>)).BuildSessionFactory();
nhibernateSession = Fluently.Configure().Database(MsSqlConfiguration.MsSql2005.ConnectionString(ConfigurationManager.AppSettings[msSqlConnectionString]))
.Mappings(m => m.AutoMappings.Add(AutoMap.Assembly(System.Reflection.Assembly.GetExecutingAssembly())
.Override<T_ABWEICHUNGEN>(map =>map.Map(d => d.A08_STATUS_FILE).Length(2147483647))
.IgnoreBase(typeof(BaseClass))
.IgnoreBase(typeof(IDColumn))
.IgnoreBase(typeof(MsSqlQuery))
.IgnoreBase(typeof(MsSqlParamCollection))
.IgnoreBase(typeof(AbweichungStatus))
)).BuildSessionFactory();
return nhibernateSession;
}
}
thanks so far for the response - helped me so far.
But - is there a way to get this solved more 'dynamicly'?
For example:
I want to declare a custom attribute called [ReadOnlyDbField] now declare all properties of the entity with this cusomt attribute to say: Just read this value and do not update / insert it.
Basically i want to say in the configuration
Map all properties with the custom attribute [ReadOnlyDbField] to Not.Insert().Not.Update()
Is there a way to implement this?
.Override<Entity>(map => map.Map(d => d.STATUS).Not.Insert().Not.Update())
update: account for edited question
public class ReadonlyDbFielConvention : AttributePropertyConvention<ReadOnlyDbField>
{
protected override void Apply(ReadOnlyDbField attribute, IPropertyInstance instance)
{
instance.Not.Insert();
instance.Not.Update();
}
}

Why both NHibernate OnPreInsert and OnPreUpdate methods get called for an object

I use the NHibernate OnPreInsert and OnPreUpdate events in a PreSaveEventListener to set the CreatedDate and ModifiedDate of my entities. The problem is, there are two entities for which both events get triggered when I first create them. This causes an issue because the entity state does not get saved after the OnPreInsert event, so the OnPreUpdate event operates on a whole new entity state and my CreatedDate never gets set (defaults to 01/01/0001).
At first, I thought this was because my code that was initiating two SaveOrUpdate calls back to back before the end of the transaction. Sure enough, I found some code to this effect. But then I realized this was still happening for the other entity. So far as I can tell, only these two entities have this issue. I temporarily solved the problem by setting the CreatedDate in their constructors, but I want to avoid this.
Here's my structure:
Business entity (an abstract class that has two concrete joined-subclasses)
BusinessContact entity with a Many-To-One relationship with Business
EDIT: I have recently realized that it's also happening on one other object (InvoiceLineItem), but not a near identical object (BillLineItem) instantiated and used in near identical ways. Seems rather arbitrary.
Has anyone seen this before?
Here's the event listener code:
public class PreSaveEventListener : IPreInsertEventListener, IPreUpdateEventListener {
public bool OnPreInsert(PreInsertEvent #event) {
EntityWithGuidId entity = #event.Entity as EntityWithGuidId;
if (null != entity) {
var createdDate = DateTime.Now;
var modifiedDate= DateTime.Now;
Set(#event.Persister, #event.State, "CreatedDate", createdDate);
Set(#event.Persister, #event.State, "ModifiedDate", modifiedDate);
entity.CreatedDate = createdDate;
entity.ModifiedDate = modifiedDate;
}
return false;
}
public bool OnPreUpdate(PreUpdateEvent #event) {
EntityWithGuidId entity = #event.Entity as EntityWithGuidId;
if (null != entity) {
var modifiedDate= DateTime.Now;
Set(#event.Persister, #event.State, "ModifiedDate", modifiedDate);
entity.ModifiedDate = modifiedDate;
}
return false;
}
private void Set(IEntityPersister persister, object[] state, string propertyName, object value) {
var index = Array.IndexOf(persister.PropertyNames, propertyName);
if (index == -1)
return;
state[index] = value;
}
}
Event listeners caused a lot of different issues in my project and many of them doesn't make sense to me. I think your issue can be caused in case when NHibernate really updates your entity after it created. NHibernate can update version of entity or set some id (or guid) for it. Can you put here mapping of issued entity? I also will suggest you to look at sql queries in profiler.
I actually ran into this, there is a chance it may be the same issue.
I implemented my own StringTrimEnd typehandler that did just that, trimmed the end of strings before inserting into the database, or after retrieving them.
Well, I implemented the Equals method wrong and it returned false for Equals(object x, object y) when x and y where null.
Therefore when I created a new object with a null string on it, it compared the loaded value (null) with the current value (null) and decided an update was needed (as well as the insert).
Maybe this will help someone out at some point.
You have nullable field in DB which wasn't marked as nullable in NH

NHibernate component mapping - Null Component

I have a mapped entity, Matter, that has a mapped component, Injury.
The only property on the Injury is DateOfInjury which is a nullable datetime.
When I retrieve the Matter, if the DateOfInjury is null, the component is null.
Thus something like this matter.Injury.DateOfInjury will throw.
Could someone explain if I am doing something obvious to cause this behaviour?
I would have expected that the Injury component gets initialized by nHibernate as an object and that the DateOfinjury property is null.
This would be more flexible i would think?
I think that's the default behavior for a component mapping. The NHibernate docs for component say that if all elements of the component are null, the component itself will just be null.
If you only have a single property in the component, it might make sense to just map it as a nullable DateTime property on the Matter class.
I also ran into the same problem of expecting NHibernate to initialize my component even if all its members are null in the DB. My motivation behind this implementation was to move as much logic concerning my component into the component, not having to deal with it being null or not.
Thanks to this post my search for an explanation why my unit tests were failing for all null values inside the component was short. I fixed this piece in the puzzle by extending the auto-property of my component class ArrivalDay and assigning a fresh instance myself when null is assigned:
private ArrivalDay _arrivalDay;
public ArrivalDay ArrivalDay
{
get { return _arrivalDay; }
set { _arrivalDay = value ?? new ArrivalDay(); }
}
This works like a charm and means very little overhead on the containing class.
I've resolved this by adding this property to my component class
public virtual bool _LoadAlways { get { return true; } set { } }
https://stackoverflow.com/a/11187173/206297 didn't work for me, but building on it:
public class Injury
{
// ...
private bool dummyFieldToLoadEmptyComponent { get; set; }
}
public class MatterMap : ClassMap<Matter>
{
// ...
Component(x => x.Injury, m =>
{
// ...
m.Map(Reveal.Member<Injury>("dummyFieldToLoadEmptyComponent")).Formula("1=1").ReadOnly();
});
}
The Reveal.Member bit is just to map a private field in Fluent NHibernate. We want the field private because we don't want that property exposed as part of our public interface to the component. See https://github.com/jagregory/fluent-nhibernate/wiki/Mapping-private-properties. If you don't mind having it public, you could use the less verbose mapping of:
m.Map(x => x.DummyFieldToLoadEmptyComponent).Formula("1=1").ReadOnly();
The Formula part is because we don't actually want a column in our DB for this. NHibernate will execute that formula when loading the component, and it'll always evaluate to true. I chose 1=1 as I would imagine that's reasonably cross-DB.
Undoubtedly a hack, but seems to work so far for loading empty components and hasn't caused any errors when persisting. Use with discretion though.
This is a technically workable solution. I have tested it with persistance and havent produced transient related issues.
protected internal virtual Injury NullableInjury {get;set;}
public virtual Injury Injury
{
get{return NullableInjury ?? (NullableInjury = new Injury());
}
In Nhibernate map your component to the NullableInjury.
This solution allows you to persist without the transient issue reported in #Oliver solution.