2011-12-28 46 views
0

讓我們成像,我們有模型:比較兩個模型在.NET

public class InheritModel 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public string Description { get; set; } 
    public string OtherData { get; set; } 
} 

我們與查看控制器,表示此型號:

private InheritModel GetAll() 
{ 
    return new InheritModel 
    { 
     Name = "name1", 
     Description = "decs 1", 
     OtherData = "other" 
    }; 
} 

public ActionResult Index() 
{ 
    return View(GetAll()); 
} 

現在,我們可以查看編輯這個,更改一些數據並返回後在服務器:

[HttpPost] 
public ActionResult Index(InheritModel model) 
{ 
    var merged = new MergeModel(); 
    return View(merged.Merge(model, GetAll())); 
} 

我需要做什麼:

  • 鑑於我們模型的再現
  • 用戶變化的東西,並張貼
  • 合併方法需要比較場逐場發佈模型和以前的型號
  • 合併方法創建數據的新InheritModel這是改變張貼模型,所有其他數據應該爲空

有人可以幫我做出這種合併方法嗎?

UPDATE(!)

這不是一個簡單的任務。接近像:

public InheritModel Merge(InheritModel current, InheritModel orig) 
{ 
    var result = new InheritModel(); 
    if (current.Id != orig.Id) 
    { 
     result.Id = current.Id; 
    } 
} 

不適用。這應該是通用解決方案。我們在該模型中有超過200個屬性。第一個模型是從DB的重要表格中構建的。

+0

難道你不能只使用[AutoMapper](http://automapper.codeplex.com/)? – Amy 2011-12-28 10:06:27

回答

5
public InheritModel Merge(InheritModel current, InheritModel orig) 
{ 
    var result = new InheritModel(); 
    if (current.Id != orig.Id) 
    { 
     result.Id = current.Id; 
    } 
    if (current.Name != orig.Name) 
    { 
     result.Name = current.Name; 
    } 
    ... for the other properties 

    return result; 
} 

另一種可能性是通過所有屬性使用反射和循環並將其值設置:

public InheritModel Merge(InheritModel current, InheritModel orig) 
{ 
    var result = new InheritModel(); 
    var properties = TypeDescriptor.GetProperties(typeof(InheritModel)); 
    foreach (PropertyDescriptor property in properties) 
    { 
     var currentValue = property.GetValue(current); 
     if (currentValue != property.GetValue(orig)) 
     { 
      property.SetValue(result, currentValue); 
     } 
    } 
    return result; 
} 

顯然,這僅適用於性能的1個嵌套。

+0

嗨!感謝您的回答,並看到我的更新:) – 2011-12-28 09:44:58

+0

如果你可以使用reflation編寫示例,它將是太棒了。 :)我昨天花了3個小時做出正確的工作方法,但沒有任何結果。 – 2011-12-28 09:47:18

+2

@EvgeniyLabunskiy,提供的例子。另外,如果您的視圖模型中有200個屬性,則應該考慮更改設計。 – 2011-12-28 09:47:44

0

我有一個類似的項目經驗,這讓我想到很多關於原始設計。想想以下問題:

您有一個觀點,即代表一個模型,然後用戶修改 東西在視圖模型,所有的CHANGES發佈到 服務器和模型進行修改,然後它可能保存到數據庫 。什麼發佈到地球上的服務器?

InheritModel的示例?不,您只需要更改。它實際上是InheritModel的一部分,它是InheritModel Updater,它是Updater<InheritModel>的一個實例。而在你的問題,你需要合併兩個模型,因爲你的Update方法是這樣的:

public InheritModel Update(InheritedModel newModel) 
{ 
    //assign the properties of the newModel to the old, and save it to db 
    //return the latest version of the InheritedModel 
} 

現在問自己:爲什麼我需要的InheritedModel整個實例的時候我只是想更新只有一個屬性?

所以我最終的解決方案是:將更改發佈到控制器,參數類似於Updater<TModel>,而不是TModel本身。並且Updater<TModel>可以是應用TModel,更新器中提到的屬性被分配並保存。不應該有MERGE操作。

+0

主要問題是我真的需要所有的InheritModel。即使有空屬性(我們有一個數據樹組織,所以如果這個屬性爲空,系統從樹中的上層記錄中獲取它) – 2011-12-28 10:07:46

+0

@EvgeniyLabunskiy:由於它是一個編輯頁面,爲什麼你需要用戶不能編輯的屬性?如果一個屬性IdentityCode是隻讀的,如果該字段是否被髮布,有什麼區別? – 2011-12-28 10:13:25

1

每個主題,似乎你想要的是一種「改變跟蹤」機制,這絕對不是微不足道的或任何手段簡單。也許,使用任何現代化的ORM解決方案爲您做到這一點是有道理的,是嗎?

因爲否則您需要開發一些維護「上下文」(第一級對象緩存)的東西,如EF的ObjectContext或NH的Session,這將是通用解決方案。

另外,沒有關於在較低級別發生什麼的信息 - 您如何實際保存數據。你是否已經有了一些通過遍歷它的「非空」屬性來保存對象的機制?

+0

是的,確切! :)我們需要跟蹤更改,但以更簡單的方式 - 只需創建具有更改數據的模型,併爲未更改的數據創建空值。 – 2011-12-28 10:13:33

+0

@EvgeniyLabunskiy,但如果你想要通用的解決方案,那麼你應該在任何地方使用這種機制 - 無論是「高」/應用程序級還是數據訪問層保存機制。我會建議後者,因爲它會更通用。而且 - 是的 - 這很複雜。最簡單的事情 - 是對所有公共屬性或屬性標記具有特殊屬性的反射。否則,你只需要對這些屬性進行比較。 – 2011-12-28 10:20:28