Создание снимка (клонирование) проекта с использованием Linq 2 Sql - PullRequest
2 голосов
/ 23 апреля 2010

У меня есть сущность Project с несколькими дочерними таблицами, например ProjectAwards ProjectTeamMember

Я хотел бы скопировать данные из Project (и дочерних таблиц) в новую запись Project и обновить статус Project.

например

var projectEntity = getProjectEntity(projectId);

draftProjectEntity = projectEntity
draftProjectEntity.Status = NewStatus

context.SubmitChanges();

Я нашел эту ссылку от Марка Гравелла

Это часть пути, но он обновляет дочерние записи до нового draftProject, куда мне нужно его скопировать.

1 Ответ

1 голос
/ 12 мая 2010

К сожалению, здесь вы устанавливаете для переменной draftProjectEntity ссылку на объект projectEntity. То есть они сейчас указывают на один и тот же объект. Что вам нужно сделать, это глубокий клон из projectEntity.

Есть способы сделать это с помощью Reflection - если вы собираетесь делать это много, - тогда я настоятельно рекомендую изучить этот метод.

Однако, если вы идете только на один уровень глубиной или только для небольшого графа объектов, то, возможно, стоит просто сделать это вручную и реализовать собственный IDeepCloneable на ваших объектах ...

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;

Для получения информации о том, почему я не использую интерфейс ICloneable для этого ... проверьте эту ветку: Должен ли я предоставить глубокий клон при реализации ICloneable?

...