我在ASP.NET MVC项目中使用POCOS作为我的模型类。到目前为止,这运行良好,但是在大多数情况下,这些Pocos包含简单类型。我现在有一个考虑使用一些复杂类型的情况,我不确定这种方法的好处。此外,我需要将单个数据库表分为多个POCO,这使我的情况变得复杂。以下示例将解释。我有一个大约40个字段的员工表。我不想始终围绕着所有属性传递这个大对象,因此我创建了3个POCO类,这些poco类表示数据的逻辑分组,如下所示:
public class EmployeeProfile
{
public int EmployeeID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Gender { get; set; }
etc ...
}
public class EmployeeContact
{
public Address Address { get; set; }
public PhoneNumber Phone { get; set; }
public string Email { get; set; }
}
public class EmploymentInfo
{
public decimal Salary { get; set; }
public string Occupation { get; set; }
etc ....
}
到目前为止还不错,但是我有时也需要整个员工表作为一个对象,这就是我不确定的地方。我可以通过将其他类型放在其中来创建员工类:
public class EmployeeDetail
{
public EmployeeProfile EmployeeProfile { get; set; }
public EmployeeContact EmployeeContact { get; set; }
public EmploymentInfo EmploymentInfo { get; set; }
}
或我可以复制三个Pocos的所有属性,包括其中包含的复杂类型,以便它是平坦的,具有简单的属性,例如:
public class EmployeeDetail
{
public int EmployeeID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Gender { get; set; }
etc ...
public Address Address { get; set; }
public PhoneNumber Phone { get; set; }
public string Email { get; set; }
public decimal Salary { get; set; }
public string Occupation { get; set; }
etc ....
}
除了包含复杂类型的版本需要较短的时间来创建POCO之外,使用一种方法比另一种方法有什么好处?我知道要重点是面向对象的,但是在这种情况下,我不确定"嵌套"这些对象是否有任何好处。在我看来,似乎将有更多的工作访问嵌套对象,并在我的视图模型和域模型之间来回翻译它们。
编辑:我想指出的是,我正在考虑的子模型不是特定视图的特定的。在整个应用程序中,它们可能会多个位置使用。这是人力资源/员工福利应用程序。我需要这些类是可以重复使用的,否则我只会将它们放在我已经使用的视图模型中。
您实际上想做的是根据将使用的视图将您的业务概念Employee
分为3个部分。因此,您想将其分为EmployeeProfile
,以在与E.G.个人资料管理等。
这样做,您将业务领域与视图域混合在一起 - 这是您应该避免的。
将域模型分开是一个很好的解决方案,以防有逻辑域拆分 具有很高的潜力,即需要分别需要某些零件。因此,一个很好的例子可能是(尽管在每种情况下都不是必不可)定义了Employee
的Address
单独的域模型。
如果我穿着你的鞋子,我会怎么做:
- 我将留下域模型
Employee
,而不会将其分成与视图相关的部分。 - 我将根据我在某个视图上需要的
Employee
模型数据的哪个部分创建单独的视图模型。 - 我认为,如果我可以将
Employee
模型分为某些与域相关的子模型(例如将地址与Employee
分开)。
从性能的角度来看,上述解决方案也可能有益。从数据库中发送几个其他字段并不是很大的麻烦,而在某些情况下,如果您需要整个副本,则需要加入您的子模型(尤其是有成千上万的员工)。
更多:从可持续性的角度来看,我也建议使用上述解决方案。从域的角度来看,使用过多的嵌套对象可能会引入一些其他挑战。CRUD操作(例如,在保存/更新整个Employee
等时需要提供提交/回滚机制)。
@bejger有一个很好的答案,但我想添加一些评论的时间。
划分数据是一个坏主意。无论您的桌子拥有40个属性还是400个都没关系,您总是最好地提供查询一张桌子,而不是与加入。现在,我刚才说的是警告。可以重复使用的数据的逻辑分组应分解。诸如地址之类的事情比一遍又一遍地重复。
具有构图,您有两个选择:
-
复杂类型:复杂类型允许您抽象要在多个类上使用的一组属性,但是在一天结束时,每个表都有自己的副本这些属性。这具有您不需要使用加入来访问数据的好处,但是它的限制是您不能包括外国钥匙或其他导航属性。
-
外键:使用外键可让您有一个表来保留此属性组的所有实例。同样,缺点是需要加入。这实际上是只有合适的选项,如果您可以预见这些属性与 Just 相互作用,否则您需要对它们进行一对多的集合。使用地址的示例,如果您想能够仅拉动所有地址而不担心员工协会,或者您希望能够为员工分配可变数量的地址,那么这是一个可行的选项。
除此之外,不必担心您的桌子尺寸。甚至具有大量列的表也比联接更有效,如果您只需要这些列的子集,则可以简单地选择所需的列(您可以使用Select
方法在LINQ中执行此操作,哪个实体框架将荣誉在查询数据库时)。
最终,我采用了完全不同的方法,而不是将我的域模型类分开并选择分开我的方法从我的域模型中读取模型,或者将其换成将R与CUD分开的另一种方式。我之所以这样做的原因是,我的应用程序中有65-75%是关于阅读和报告数据,而不是创建,更新或删除它。
因此,在这种情况下,我将作为我的域名实体,没有组成的完整员工模型:
public class Employee
{
public int EmployeeID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Gender { get; set; }
etc ...
public Address Address { get; set; }
public PhoneNumber Phone { get; set; }
public string Email { get; set; }
public decimal Salary { get; set; }
public string Occupation { get; set; }
etc ....
}
除了在读取方面,我可能有以下内容:
public class EmployeeRoster
{
public int EmployeeID { get;set;}
public string FullName { get;set; }
public decimal Salary { get;set; }
public string Occupation { get;set;}
public DateTime DateOfHire { get;set;}
}
以及我在阅读侧需要的其他任何对象。这听起来很像CQRS(命令查询责任隔离),我已经知道CQR已有一段时间了,但是我在CQR上看到的资源令人失望。例如,通常建议人们使用不同的数据库进行读取操作与写入。虽然我明白为什么人们可能想这样做(表现),但就我的目的而言,这是过分的。此外,CQR上的大多数资源都表明,将读取查询直接映射到查看模型。我有一些问题。一种,在许多情况下,我需要重复使用这些读取模型。我的应用程序中的多个位置都使用了诸如simpleeroster之类的东西。另外,在某些情况下,我需要在视图模型消耗读取对象之前将业务逻辑应用于读取对象。
总而言之,在这一点上,我敢肯定我需要一个单独的读取模型,但是我不一定相信CQRS正式练习是必经之路。因此,我目前已经回答了自己的问题,但还没有接受这一点,因为我认为其他具有更多独立阅读模型和/或CQR经验的人可以比我提供更好的答案。