[英]Entities VS Domain Models VS View Models
關於這個主題有數百個類似的問題。 但是我仍然很困惑,我想為此尋求專家的建議。
我們正在使用ASP.NET MVC 4和EF5開發應用程序,而我們的方法是數據庫優先方法。
我們在一個單獨的項目中有一個數據層,該項目是一個類庫,其中包含所有定義的實體。 然后使用所有存儲庫和域模型定義業務層(這是要使用的正確術語)。 然后是表示層。
目前,我們尚未定義任何視圖模型,我們正在使用BL中與視圖模型相同的域模型。 在這種方法中,一個映射就足夠了。
實體<=>域模型
但是對我來說,它看起來並不是一個好的設計。 我更喜歡在表示層中定義視圖模型,並使用域模型在表示層和業務層之間進行通信。 在BL上,將域對象轉換為數據實體並與DAL通信。 使用這種方法,我必須使用兩次映射。
查看模型<=>域模型<=> ENTITY
我的域模型真的必要嗎? 我不能使用我的實體與Presentation層進行通信。 如果我在表示層中引用實體,會有什么影響? 如果有什么樣的影響?
我認為您在定義每個層是什么以及它在解決方案中扮演什么角色時遇到了問題。
您的數據層就是您的數據庫/ SharePoint列表/ .csv文件/ excel工作表...您就知道了,它只是數據的存儲位置,並且可以是任何格式。 因此請記住,數據層不過是數據而已。
// ----------------------------
// Data tier
// - MySQL
// - MS SQL
// - SharePoint list
// - Excel
// - CSV
// - NoSQL
// ----------------------------
該層抽象了您的數據源,並提供了一個API,您的其余應用程序可以在其中與數據源進行交互。
考慮我們的數據源是一個MS SQL數據庫,並且我們正在使用Entity Framework訪問數據。 您將嘗試抽象的是數據庫和Entity Framework,並且每個Entity
都有一個Data Repository
。
我們在MS SQL數據庫中有一個Customers
表。 客戶表中的每個客戶都是一個Entity
,並在您的C#代碼中表示為。
通過使用存儲庫模式,我們可以抽象化數據訪問代碼的實現,以便將來,如果我們的數據源發生更改,我們應用程序的其余部分將不會受到影響。 接下來,我們將在Data Access Layer
需要一個CustomersRepository
,其中將包括Add
, Remove
和FindById
。 提取任何數據訪問代碼。 下面的示例是如何實現此目的的。
public interface IEntity
{
int Id { get; set; }
}
public class Customer : IEntity
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime RegistrationDate { get; set; }
}
public interface IRepository<TEntity> where TEntity : class, IEntity
{
TEntity FindById(int id);
void Add(TEntity entity);
void Remove(TEntity entity);
}
public class CustomerRepository : IRepository<Customer>
{
public Customer FindById(int id)
{
// find the customer using their id
return null;
}
public void Add(Customer customer)
{
// add the specified customer to the db
}
public void Remove(Customer customer)
{
// remove the specified customer from the db
}
}
數據訪問層屬於數據層和業務邏輯之間。
// ----------------------------
// Business logic
// ----------------------------
// ----------------------------
// Data access layer
// - Repository
// - Domain models / Business models / Entities
// ----------------------------
// ----------------------------
// Data tier
// - MySQL
// - MS SQL
// - SharePoint list
// - Excel
// - CSV
// - NoSQL
// ----------------------------
業務層建立在數據訪問層之上,不處理任何數據訪問問題,而是嚴格處理業務邏輯。 如果業務要求之一是阻止從英國境外下訂單,則業務邏輯層將處理此問題。
表示層僅表示數據,但是如果您不關心呈現的數據以及允許發布的數據,則會使自己陷入困境,這就是為什么使用視圖模型非常重要,因為視圖模型是表示層的關注點,所以表示層不需要了解有關您的域模型的任何知識,只需要了解視圖模型即可。
那么什么是View Models ...它們只是為每個視圖量身定制的數據模型,例如注冊表單將包含RegistrationViewModel
,從而暴露了這些典型屬性。
public class RegistrationViewModel
{
public string Email { get; set; }
public string Password { get; set; }
public string ConfirmPassword { get; set; }
}
表示層還處理輸入驗證,例如,驗證鍵入的電子郵件地址是否具有正確的格式,或者驗證輸入的密碼是否與表示層有關,而與業務無關,並且可以使用Data Annotations
來處理。
public class RegistrationViewModel
{
[Required]
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
[Required]
[DataType(DataType.Password)]
[Compare("ConfirmPassword")
public string Password { get; set; }
[Required]
[DataType(DataType.Password)]
public string ConfirmPassword { get; set; }
}
使用視圖模型很重要的原因是,由於業務模型屬於業務層,並且它們包含應保留為私有的數據。 例如,如果要在JSON響應中公開域模型,則它將公開用戶的全部數據,用戶的姓名和地址,因為您對所公開的內容和不存在的內容沒有選擇,而是使用任何似乎正在工作。
我還要在這里指出, domain models
和entity models
之間是有區別的。 已經有一個答案, 這里有更多詳細信息
我將簡要介紹一下:
我不是專家,但我將分享我在該主題上的50美分。
我想分享您對忽略視圖模型的關注。
使用視圖模型,您可以:
因此,我也認為這是一個不好的設計,但其他人可能有不同的看法。
記住,業務層對視圖模型一無所知,因此您應該在控制器中進行映射。
我將使用POCO作為可以與ORM或NoRM保持一致的域模型來簡單地開始。 對於世界上開發的大多數軟件而言,它不會對您的系統造成太大的傷害,而且也很簡單。
將來,如果由於某種原因開始使用Web服務,則可能需要考慮將DTO(數據傳輸對象)用於遠程調用。 在那里,您所要做的就是擁有另一層,負責將您的域模型映射到所需的DTO。 該層僅在遠程調用(Web服務)中使用,保留表示的視圖模型。
引入其他類的主要好處是關注點分離:
這只能通過ViewModels和Domain Entities的兩個模型類來實現。 與其使用類似於持久化實體的單獨模型類對域邏輯進行建模,不如在使用域實體的服務類中實現它。 域實體最多應具有處理其自身屬性的邏輯(例如,將兩個屬性的組合值保持在有效狀態)。 如果一個用例影響多個域實體,請在服務類中對該用例建模。 如果您在實體類中直接放置邏輯來管理實體之間的關系,則代碼將變得非常難以維護(相信我,我嘗試過)。
我不建議將可持久性實體用作ViewModels,因為這會將顯示問題(例如[DisplayName]
)與持久性問題(例如[ForeignKey]
)混合在一起。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.