如何将实体从一个Entity Framework上下文复制到另一个实体框架上下文?

ali*_*lik 12 .net c# entity-framework entity-framework-6

如何将实体从一个上下文(继承DbContext)复制到另一个上下文?

我发现的所有东西只适用于ObjectContext但不适用于DbContext或使用DbContext但不起作用.

例如,我发现/尝试过:

  • 在CodeProject上使用ObjectContext:CloneHelper
  • 将LazyLoadingEnabled设置为false会导致无法填充ICollection <>属性(外键)
  • 将ProxyCreationEnabled设置为false会导致ICollection <>属性保持为null(外键)
  • Entry <> .State = Detached导致未填充ICollection <>属性(外键)(如果在附加属性之前设置),或者阻止清除Id(如果稍后设置).
  • AsNoTracking()导致异常(以下之一,取决于是否首先从父级的ICollection <>属性或首先插入父级)向远程上下文插入一个项目:
    • 父级:"ModelFirstSub_First_Target"角色中的对象无法自动添加到上下文中,因为它是使用NoTracking合并选项检索的.在定义关系之前,将实体显式附加到ObjectContext.
    • 项目:无法添加或附加对象,因为其EntityReference具有与此对象的EntityKey不匹配的EntityKey属性值.

我将它用于两个目的:

  1. 将所有内容从一个数据库复制到另一个数据库(目标将是原始数据库的克隆;远程数据库的本地副本).应保留一堆对象.
  2. 将所选实体从一个数据库添加或更新到另一个数据库(本地缓存中的上游更改为远程源).不需要保留新创建的对象的ID.

怎么做?

EF 6.1.1,.NET 4.5.2,C#

以下是尝试模拟第二个操作的测试代码(上游更改回远程数据库):

var addedFirst = localContext.Firsts.AsNoTracking().Single(m => m.Id == 4);
var updatedFirst = localContext.Firsts.AsNoTracking().Single(m => m.Id == 2);

addedFirst.Items.First().Id = 0;
addedFirst.Items.First().FirstId = 0;
addedFirst.Id = 0;

remoteContext.FirstItems.Add(addedFirst.Items.First());
remoteContext.Firsts.Add(addedFirst);

var originalFirst = remoteContext.Firsts.Single(m => m.Id == 2);
var originalItem = originalFirst.Items.First();
originalItem.Title = updatedFirst.Items.First().Title;
Run Code Online (Sandbox Code Playgroud)

这是模型:

public class ModelFirstBase
{
    public virtual int Id { get; set; }
    public virtual ICollection<ModelFirstSub> Items { get; set; }
    public virtual string Title { get; set; }
}

public class ModelFirstSub
{
    public virtual int Id { get; set; }
    public virtual int FirstId { get; set; }
    public virtual ModelFirstBase First { get; set; }
    public virtual string Title { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

PS:随着模型与生产应用程序共享,属性需要保持虚拟,这将受益于动态代理.

Sum*_*ngi 0

您是否尝试简单地将模型转换为第二个模型:

public class ModelFirstBase
{
public virtual int Id { get; set; }
public virtual ICollection<ModelFirstSub> Items { get; set; }
public virtual string Title { get; set; }
}

public class ModelFirstSub
{
public virtual int Id { get; set; }
public virtual int FirstId { get; set; }
public virtual ModelFirstBase First { get; set; }
public virtual string Title { get; set; }
}

public class ModelTranslator
{
public ModelFirstSub TranslateModelFirstBase(ModelFirstBase entity)
{
//do some error handling and null checks.
var second = new ModelFirstSub(){
                  FirstId = entity.Id,
                  .....
             };
return second;
}
}

public void TransferModels(){ //I haven't thought about disposing stuff, you should.
var firstContext = new FirstContext();
var secondContext = new SecondContext();
foreach (var first in firstContext.ModelFirstBases){
     var second = new ModelTranslator().TranslateModelFirstBase(first);
     secondContext.ModelFirstSubs.Add(second);
}
secondContext.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)

但请注意,EF 并不用于批量复制数据,尽管这应该可行,但这并不是一个实际的解决方案。如果使用 Sql 服务器或任何您可能使用的数据库的等效项,您应该考虑 SqlBulkCopy。

SQLBulkCopy:SqlBulkCopy 如何工作