2014-10-27 108 views
11

如何將實體從一個上下文(從DbContext繼承)複製到另一個上下文中?如何將實體從一個實體框架上下文複製到另一個實體?

我找到的所有東西只能用於ObjectContext,但不適用於DbContext或使用DbContext,但不起作用。

例如,我已發現/嘗試:

  • 用途的ObjectContext:CloneHelper在CodeProject
  • 設定LazyLoadingEnabled錯誤的結果中未填充的ICollection <>性質(外國鍵)
  • 設置ProxyCreationEnabled爲false將ICollection <>屬性保留爲空(外鍵)
  • 條目<> .State =分離導致未填充ICollection <>屬性(外鍵)如果在附加屬性之前設置,或者在稍後設置時阻止清除標識。
  • AsNoTracking()導致異常(以下情況之一,取決於是否從父的ICollection的<>屬性或第一父插入到遠程上下文第一項):
    • 父級:在對象中的' ModelFirstSub_First_Target'角色不能自動添加到上下文,因爲它使用NoTracking合併選項進行檢索。在定義關係之前,明確地將實體附加到ObjectContext。
    • 項目:該對象無法添加或附加,因爲其EntityReference具有與該對象的EntityKey不匹配的EntityKey屬性值。

我會用它有兩個目的:

  1. 複製從一個數據庫到另一個(目標將是原始的克隆;遠程數據庫的本地副本)。應保留對象的ID。
  2. 將所選實體從一個數據庫添加或更新到另一個數據庫(將本地高速緩存中的更改上傳到遠程原點)。新創建的對象的ID不需要被持久化。

如何執行該操作?

EF 6.1.1,4.5.2 .NET,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; 

這裏是模型:

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; } 
} 

PS:屬性需要作爲模型與生產應用程序,它從動態代理益共享被保持虛擬的。

+0

你有沒有嘗試上下文分離和附加方法? – 2014-10-27 21:22:45

+1

DbContext上沒有這樣的方法。 – alik 2014-10-27 21:32:28

+0

Context.Set ().Attach(poco)或Context.Set(類型pocoType).Attach(poco)版本。 DbContext支持許多表類型。您正在附加/分離到(n)個集合之一。不是直接上下文 – 2014-10-27 21:39:06

回答

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(); 
} 

但是做注意,EF並不意味着對數據的批量複製,這即使應該工作是不是一個實際的解決方案。你應該考慮使用SqlBulkCopy,而不是使用Sql服務器或者任何你可能使用的數據庫。

SqlBulkCopy的:How does SqlBulkCopy Work

+0

將ModelFirstBase翻譯爲ModelFirstSub似乎很奇怪。即使如此,我還是希望能夠在不使用任何對象間的轉換的情況下(爲此我可以利用克隆,業務模型或一些自動映射器類)。 – alik 2014-10-31 09:57:04

+0

如果您願意,您可以使用自動映射器,這是一個相同的優秀庫:http://automapper.org/。請記住,任何「自動」映射都將使用反射,並且不會是高性能,所以如果這是在後臺運行並且幾毫秒(以及更高的CPU使用率)並不重要的事情,請繼續。如果你有單獨的實體類,你不能避免翻譯。但是,您可以使用相同的類並針對不匹配的屬性使用EntityTypeConfiguration(http://msdn.microsoft.com/en-us/library/gg696117(v=vs.113).aspx)。 – 2014-10-31 10:42:12

相關問題