2016-03-10 114 views
1

我先使用代碼,並有一些實體需要每個工作的「工作進行中」版本。傳統上,我們已經通過克隆所有這些實體的表並添加了前綴「wip」來實現此模式。版。雖然這個系統的工作原理有很多醜陋的代碼,我希望找到一個乾淨利落的解決方案使用實體框架。工作進行中/實體克隆

理想我喜歡的東西接近這個:

using (MyDBContext ctx = new MyDBContext()) { 
    Person myPerson = ctx.First(x => x.Name == "frank"); 
    // Do work with the non "work in progress" entities 
} 

using (MyWIPContext wipCtx = new MyWIPContext()) { 
    Person myPerson = wipCtx.First(x => x.Name == "frank"); 
    // Do work with the "work in progress" entites 
    // If I need to move this entity to non "Work in Progress" maybe do: 
    ctx.Attach(myPerson); 
    ctx.SaveChanges(); // Where ctx is the non "Work in Progress context" 
} 

從我挖我覺得這是可能的。我發現我可以添加一個規則來前綴「wip」。在我的表(How to Add Table Prefix In Entity Framework Code First Globally?)的前

還發現了一個後處理多種模式的(Entity Framework and multiple schemas)引用這篇文章(http://romiller.com/2011/05/23/ef-4-1-multi-tenant-with-code-first/

一些我打的問題是使用遷移創建數據庫。如果我有多個DBContext的遷移開始變得混亂,並與第二篇文章,他們根本不工作,因爲他們不給那裏DBContext一種方式來構建,以便遷移失敗。

有誰知道一個乾淨的方式來實現這種模式。我很樂意儘可能地讓它不突兀。實體不應該意識到他們有2個地方可以堅持(正在進行中&真實版本)。我知道我可以通過向實體添加標誌來做到這一點,但我覺得還有另一種方式。

+0

您正在使用哪個EF版本? – tede24

+0

它是一個新項目,所以我可以使用最新和最好的 – Mikeb

+0

因此,如果您使用EF6,遷移和多個dbcontext的問題不再存在。執行命令時只需設置「Configuration」參數。 http://stackoverflow.com/questions/21537558/multiple-db-contexts-in-the-same-db-and-application-in-ef-6-and-code-first-migra。我在你的方法中看到的問題是關於管理ID和FK,以防在WIP區域中創建新實體並使用數據庫生成的身份 – tede24

回答

1

您可以有2個班級(LivePersonWipPerson)繼承您當前的Person班。然後你會告訴Entity Framework將每個類映射到不同的表。

EF配置:

modelBuilder.Entity<LivePerson>() 
    .Map(m => m.MapInheritedProperties() 
     .ToTable("Persons")); 

modelBuilder.Entity<WipPerson>() 
    .Map(m => m.MapInheritedProperties() 
     .ToTable("WipPersons")); 

然後,你可以這樣做:

// Create Frank 
using (var db = new Db()) 
{ 
    // Create Frank 
    LivePerson frank = new LivePerson { Name = "Frank" }; 

    // Clone Frank 
    WipPerson wipFrank = Clone<LivePerson, WipPerson>(frank); 

    // Add to database and save 
    db.Persons.Add(frank); 
    db.WipPersons.Add(wipFrank); 
    db.SaveChanges(); 
} 

// Edit WIP 
using (var db = new Db()) 
{ 
    var wipFrank = db.WipPersons.First(/*Todo: Use query*/); 

    wipFrank.Notes = "Okay"; 

    db.SaveChanges(); 
} 

這會給你同樣的事情,但在單獨的表的副本。然而,還有一個新的複雜性:你必須能夠將一個人從一種類型克隆到另一種類型。

我用這個方法:

private static TOut Clone<TIn, TOut>(TIn obj) 
{ 
    // using Newtonsoft.Json; 
    return JsonConvert.DeserializeObject<TOut>(JsonConvert.SerializeObject(obj)); 
} 

如果你的人是很簡單的克隆,我認爲這個解決方案可能會奏效...... 或者至少你可以從一種類型的集中整治克隆到另一個根據您的需求。

該解決方案還允許您進一步向WipPerson類添加一些屬性,以跟蹤克隆的創建時間,創建者,最後編輯者,克隆的創建日期等等。上。