Adr*_*tov 46 c# architecture orm domain-driven-design domain-model
我一直在阅读有关域驱动设计以及如何使用代码优先方法生成数据库的方法.根据我的阅读和研究,围绕这个主题有两种观点:
有1个类同时用作域模型和持久性模型
有2个不同的类,一个实现域逻辑,一个用于代码优先方法
现在我知道意见1)据说简化了在域和持久性模型之间没有太多差异的小解决方案,但我认为它打破了单一责任原则,并且当ORM的约定干扰DDD时引入了许多问题.
令我感到意外的是,有很多关于如何实现意见的代码示例1).但是还没有找到一个如何实现意见的例子2)以及如何映射这两个对象.(可能有这样的例子,但我找不到C#)
所以我试着自己实现一个例子,但我不确定这是不是一个很好的方法.
假设我有一个票务系统,票证有到期日.我的域名模型如下所示:
/// <summary>
/// Domain Model
/// </summary>
public class TicketEntity
{
public int Id { get; private set; }
public decimal Cost { get; private set; }
public DateTime ExpiryDate { get; private set; }
public TicketEntity(int id, decimal cost, DateTime expiryDate)
{
this.Id = id;
this.Cost = cost;
this.ExpiryDate = expiryDate;
}
public bool IsTicketExpired()
{
if (DateTime.Now > this.ExpiryDate)
{
return true;
}
else
{
return false;
}
}
}
Run Code Online (Sandbox Code Playgroud)
使用Entity Framework作为ORM的持久性模型看起来几乎相同,但随着解决方案的增长,情况可能并非如此
/// <summary>
/// ORM code first Persistence Model
/// </summary>
public class Ticket
{
[Key]
public int Id { get; set; }
public decimal Cost { get; set; }
public DateTime ExpiryDate { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
到目前为止,一切看起来都很棒 现在我不确定哪个是Ticket从存储库中获取持久性模型的最佳位置以及如何将其映射到TicketEntity域模型
我在应用程序/服务层完成了这项工作.
public class ApplicationService
{
private ITicketsRepository ticketsRepository;
public ApplicationService(ITicketsRepository ticketsRepository)
{
this.ticketsRepository = ticketsRepository;
}
public bool IsTicketExpired(int ticketId)
{
Ticket persistanceModel = this.ticketsRepository.GetById(ticketId);
TicketEntity domainModel = new TicketEntity(
persistanceModel.Id,
persistanceModel.Cost,
persistanceModel.ExpiryDate);
return domainModel.IsTicketExpired();
}
}
Run Code Online (Sandbox Code Playgroud)
我的问题是:
是否有任何理由意见1)除了加速开发和重用代码之外,更倾向于意见2).
我的模型映射方法有什么问题吗?当解决方案增长时,我错过了哪些会带来问题?
jga*_*fin 24
是否有任何理由意见1)除了加速开发和重用代码之外,更倾向于意见2).
选项1只是因为纯粹的懒惰和想象的增加的开发速度.确实,这些应用程序将更快地构建版本1.0.但是当这些开发人员达到应用程序的3.0版时,他们认为维护应用程序并不是那么有趣,因为由于ORM映射器,他们必须在域模型中做出妥协.
我的模型映射方法有什么问题吗?当解决方案增长时,我错过了哪些会带来问题?
是.存储库应负责隐藏持久性机制.它的API应该只适用于域实体而不是持久性实体.
存储库负责与域实体进行转换(以便能够持久化它们).fetch方法通常使用ADO.NET或ORM(如Entity Framework)来加载数据库对象/实体.然后将其转换为正确的业务实体,最后返回它.
否则,您将强制每个服务都了解持久性和使用您的域模型,因此有两个职责.
如果按照DDD定义使用应用程序服务,则可能需要查看可替代应用程序服务的命令/查询分隔模式.代码变得更清晰,您还可以获得包含域模型的更轻量级的API.
fab*_*tto 12
我在今年的一个大项目中遇到了这个困境,这是一个非常艰难的决定......我想在几个小时内讨论这个话题,但我会为你重新开始思考:
如果你是一个新项目,其数据库设计为零,我可能会建议这个选项.是的,域和您对它的了解将不断变化,这将需要重构,这将影响您的数据库,但我认为在大多数情况下它是值得的.
使用Entity Framework作为您的ORM,您几乎可以使用流畅的映射使您的域模型完全不受ORM问题的影响.
好的部分:
坏的部分:
它可以让您随意使用您的域名做任何事情.不用担心重构,也不担心ORM和数据库的限制.对于处理遗留或设计糟糕的数据库的系统,我会推荐这种方法,这可能会破坏你的域名.
好的部分:
坏的部分:
在层之间进行数据转换的更多努力.开发时间(也许还有运行时)会变慢.
但校长,并相信我,会有更多的伤害:你将失去使用ORM的主要好处!像跟踪更改.也许你最终会使用像GraphDiff这样的框架,甚至放弃ORM,转到纯ADO.NET.
我的模型映射方法有什么问题吗?
我同意@jgauffin:"它应该在存储库中进行映射".这样,您的Persistence模型永远不会从Repository层中退出,优先,没有人应该看到这些实体(除非存储库本身).
| 归档时间: |
|
| 查看次数: |
5832 次 |
| 最近记录: |