Higune
Higune

Reputation: 653

fluent nhibernate copy a full entity

how can I best copy an entity instance in fluent nhibernate 3.3.1; I read an object out of the database, I got an object, now I change some values of this object. This object with little changes want I save.

I have tried to set the Id to 0, this is not working, also I write a Clone method in my Entityclass. Here is my approach.

public class Entity: ICloneable
{
    public virtual int Id { get; protected set; }

    object ICloneable.Clone()
    {
        return this.Clone();
    }

    public virtual Entity Clone()
    {
      return (Entity)this.MemberwiseClone();
    }
}

Do you some tips for me.

Upvotes: 3

Views: 4514

Answers (2)

Mez
Mez

Reputation: 4726

You need to

  1. Load entity with NH
  2. Clone the entity with method below, and create copy
  3. Evict main entity
  4. Do changes to copy
  5. Update the copy, without any reference to the main entity

The clone method is as follows

         /// <summary>
     /// Clone an object without any references of nhibernate
     /// </summary> 
    public static object Copy<T>(this object obj)
    {
        var isNotSerializable = !typeof(T).IsSerializable;
        if (isNotSerializable)
            throw new ArgumentException("The type must be serializable.", "source");

        var sourceIsNull = ReferenceEquals(obj, null);
        if (sourceIsNull)
            return default(T);

        var formatter = new BinaryFormatter();
        using (var stream = new MemoryStream())
        {
            formatter.Serialize(stream, obj);
            stream.Seek(0, SeekOrigin.Begin);
            return (T)formatter.Deserialize(stream);
        }
    }

To use it you call it as follows

object main;
var copy = main.Copy<object>();

To see some other opinions on what to use, you can view this link aswell Copy object to object (with Automapper ?)

Upvotes: 1

valverij
valverij

Reputation: 4941

If your objects are not serializable and you are just looking for a quick one-to-one copy of them, you can do this pretty easily with AutoMapper:

// define a one-to-one map
// .ForMember(x => x.ID, x => x.Ignore()) will copy the object, but reset the ID
AutoMapper.Mapper.CreateMap<MyObject, MyObject>().ForMember(x => x.ID, x => x.Ignore());

And then when you copy method:

// perform the copy
var copy = AutoMapper.Mapper.Map<MyObject, MyObject>(original);

/* make copy updates here */

// evicts everything from the current NHibernate session
mySession.Clear();

// saves the entity
mySession.Save(copy); // mySession.Merge(copy); can also work, depending on the situation

I chose this approach for my own project because I have a lot of relationships with some weird requirements surrounding record duplication, and I felt this gave me a little more control over it. Of course the actual implementation in my project varies a bit, but the basic structure pretty much follows the above pattern.

Just remember, that the Mapper.CreateMap<TSource, TDestination>() creates a static map in memory, so it only needs to be defined once. Calling CreateMap again for the same TSource and TDestination will override a map if it's already defined. Similarly, calling Mapper.Reset() will clear all of the maps.

Upvotes: 2

Related Questions