views:

58

answers:

1

I have a Project entity with several child tables, eg ProjectAwards ProjectTeamMember

I would like to copy the data from Project (and child tables) into a new Project record and update the Project status.

eg

var projectEntity = getProjectEntity(projectId);

draftProjectEntity = projectEntity
draftProjectEntity.Status = NewStatus

context.SubmitChanges();

I found this link from Marc Gravell

Its part of the way there but it updates the child records to the new draftProject, where I need it to copy.

A: 

Unfortunately what you are doing here is setting the variable draftProjectEntity to a reference to the projectEntity object. That is, they are now pointing to the same object. What you need to do is a deep clone of projectEntity.

There are ways of doing this with Reflection - if you are going to do this a lot - then I strongly suggest you look into this method.

However, If your only going one level deep, or only for a small graph of objects, then it might be worth simply doing it by hand and implementing your own IDeepCloneable on your entities...

public interface IDeepCloneable<T>
{
    T DeepClone();
}

public class Person : IDeepCloneable<Person> 
{
    public string Name { get; set; }
    public IList<Address> Addresses { get; set; }

    public Person DeepClone()
    {
        var clone = new Person() { Name = Name.Clone().ToString() };

        //have to make a clone of each child 
        var addresses = new List<Address>();
        foreach (var address in this.Addresses)
            addresses.Add(address.DeepClone());

        clone.Addresses = addresses;
        return clone;
    }
}

public class Address : IDeepCloneable<Address>
{
    public int StreetNumber { get; set; }
    public string Street { get; set; }
    public string Suburb { get; set; }

    public Address DeepClone()
    {
        var clone = new Address()
                        {
                            Street = this.Street.Clone().ToString(),
                            StreetNumber = this.StreetNumber, //value type - no reference held
                            Suburb = this.Suburb.Clone().ToString()
                        };
        return clone;
    }
}

//usage:
var source = personRepository.FetchByName("JoeBlogs1999");
var target = source.DeepClone();

//at this point you could set any statuses, or non cloning related changes to the copy etc..

targetRepository.Add(target);
targetRepository.Update;

For info on why I'm not using the ICloneable interface for this... check this thread: http://stackoverflow.com/questions/151520/should-i-provide-a-deep-clone-when-implementing-icloneable

Jim Burger
thanks for the answer, I had found and seen similar implementations for cloning, I was hoping there would be a piece of Linq 2 SQL magic that would do it for me along the lines of the pseudo question code.
JoeBlogs1999