使用 Linq 2 Sql 拍摄项目快照(克隆)

发布于 2024-08-30 03:23:34 字数 509 浏览 3 评论 0原文

我有一个带有多个子表的项目实体,例如 ProjectAwards ProjectTeamMember

我想将项目(和子表)中的数据复制到新的项目记录中并更新项目状态。

例如,

var projectEntity = getProjectEntity(projectId);

draftProjectEntity = projectEntity
draftProjectEntity.Status = NewStatus

context.SubmitChanges();

我发现此链接来自 Marc Gravell

它是其中的一部分,但它将子记录更新到新的 DraftProject,我需要它复制。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

葬心 2024-09-06 03:23:35

不幸的是,您在这里所做的是将变量 draftProjectEntity 设置为对 projectEntity 对象的引用。也就是说,它们现在指向同一个对象。您需要做的是 projectEntity深度克隆

有多种方法可以通过反射来做到这一点 - 如果您打算经常这样做 - 那么我强烈建议您研究一下这种方法。

但是,如果您只深入一层,或者仅针对一小部分对象,那么可能值得简单地手动完成并在您的实体上实现您自己的 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 时的深度克隆?

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: Should I provide a deep clone when implementing ICloneable?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文