2016-04-27 38 views
0

我的模型看起来像这样一个模型:复制具有层次

Company 
-Locations 

Locations 
-Stores 

Stores 
-Products 

所以我想使公司的副本,及其所有关联也应该复制并保存到数据库中。

如果我将公司加载到内存中,我该怎么做?

Company company = DbContext.Companies.Find(123); 

如果它很棘手,我可以遍历每个关联,然后调用创建一个新的对象。身份证将是不同的,但其他一切应该是相同的。

我使用EF 6.

回答

0

我想补充一个方法需要可复制这样每个模型,我推荐一个接口也。

这是可以做到这样的事:

//Company.cs 
Company DeepClone() 
{ 
    Company clone = new Company(); 

    clone.Name = this.name; 
    //...more properties (be careful when copying reference types) 

    clone.Locations = new List<Location>(this.Locations.Select(l => l.DeepClone())); 

    return clone; 
} 

你应该重复这个基本模式为每级和“孩子”类必须是可复制的。通过这种方式,每个对象都知道如何创建自身的深层克隆,并将子对象的责任传递给子类,整齐地封装所有内容。

它可以这样使用:

Company copyOfCompany123 = DbContext.Companies.Find(123).DeepClone; 

我道歉,如果在上面的代码中的任何错误;目前我没有Visual Studio来验证所有内容,我正在从内存中工作。


另外一个非常简单和代码有效的方式来使用序列深克隆对象可以在这个帖子中找到How do you do a deep copy an object in .Net (C# specifically)?

public static T DeepClone<T>(T obj) 
{ 
using (var ms = new MemoryStream()) 
{ 
    var formatter = new BinaryFormatter(); 
    formatter.Serialize(ms, obj); 
    ms.Position = 0; 

    return (T) formatter.Deserialize(ms); 
} 
} 

要知道,这可能有一些非常严重的资源和性能问题取决于你的对象结构。每个想要使用它的课程也必须标注[Serializable]属性。

2

克隆与EF对象图是小菜一碟:

var company = DbContext.Companies.AsNoTracking() 
         .Include(c => c.Locations 
          .Select(l => l.Stores 
           .Select(s => s.Products))) 
         .Where(c => c.Id == 123) 
         .FirstOrDefault(); 
DbContext.Companies.Add(company); 
DbContext.SaveChanges(); 

有几件事情,这里要注意。

  • AsNoTracking()是至关重要的,因为您添加到上下文的对象不应该被跟踪。
  • 现在如果你Add()company,其对象图中的所有实体也将被标记为Added
  • 我假定数据库生成新的主键值(标识列)。如果是这样,EF将忽略来自数据库中现有对象的当前值。如果不是,则必须遍历对象图并自己分配新值。

一个告诫:只有当关联是1:0..n时,这才会有效。如果存在n:m关联,则可能会多次插入相同的实体。例如,如果Store-Product是n:m并且product A发生在store 1store 2,则product A将被插入两次。如果您想防止这种情况发生,您应该在一个新的上下文中通过一个上下文获取对象,并跟踪(即没有0​​)和Add()。通过启用跟踪,EF可以跟踪相同的实体并且不会重复它们。在这种情况下,应该禁用代理创建,否则实体会保留对它们来自的上下文的引用。

更多细节在这里:Merge identical databases into one

+0

我使用的UnitOfWork,我怎么能脱离正确? http://www.asp.net/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns- in-an-asp-net-mvc-application –

+0

你不*有*使用它。不要让你自己的建筑扼杀你。这个通用的存储库使得使用EF的功能变得非常困难。如果你想要如何使用'AsNoTracking'? –

+0

但是现在怎么不能重构一切。我必须改变一切,那么对吗? –