服务层和仓储层的职责

3

我需要一些关于服务和仓库界限的建议。

在IT技术方面,这是关于如何管理代码库和提供的服务之间的关系的问题。
public class Contact
{
     public Guid Id {get;set;}
     public string Username {get;set;}
     public Guid? AvatarId {get;set;}
     public Avatar Avatar {get;set;}
}

public class Avatar
{
     public Guid Id {get;set;}
     public string FullSizeImagePath {get;set;}
     public string ThumbnailSizeImagePath {get;set;}
}

假设Avatar模型仅用于Contact模型,并且它是联系人的可选属性。那么,我的存储库是否应负责向联系人添加Avatar,还是业务/服务层应扩展该功能?有人可能会认为,拥有头像是业务要求,但由于它是模型的一部分,数据层应知道如何处理它。
我建议我们通过存储库添加添加/更新和删除Avatar的功能。业务/服务层将负责保存物理文件、验证和调用存储库上适当的方法。存储库只关心将适当的联系人附加到并向其添加Avatar。
我的思路是,由于头像仅在联系人上使用,因此我们将扩展存储库,并因此将功能添加到DAL中。这对于单独的API可能很有用。

2
离题一下,既然您可以通过“Avatar.Id”访问它,为什么还需要在“Contact”类中拥有“AvatarId”属性? - sll
1
@sll 我认为这是Entity Framework(Code First)所需的,以帮助定义导航属性Avatar。 - Mike Hanrahan
@MikeHanrahan 绝对不需要使用 EF。关系可以通过使用 Avatar 进行映射。 - Yuck
@Yuck,虽然这不是必需的,但它允许您在该实体的映射中指定空值。 - DDiVita
@Yuck,你确定吗?过去如果我没有将键属性设置为可空,我会在插入时收到一个错误,从EF中会出现FK关系错误,除非我手动进入数据库并将Avatar_Id(如果我在映射中未指定FK,则由EF生成)设置为允许为空。我认为在代码优先中不设置键也是一样的。因此,如果我不将Guid设置为可空,我应该会收到相同的约束错误。 - DDiVita
显示剩余3条评论
1个回答

1
在我看来,我不会将其添加到您的存储库中,而是在业务层中定义它。
如果您遵循领域驱动设计,您的“Contact”将获得一个“AddAvatar”方法,该方法将负责创建“Avatar”并设置正确的属性。
仓库仅为聚合根创建。由于您已经声明“Avatar”只能通过您的“Contact”访问,因此您的数据层不应包含“AvatarRepository”。您可以通过相应的联系人加载“Avatar”。
您还声明BLL将负责保存实际文件。我认为这需要考虑一下。您真的想要处理物理文件的代码在BLL中吗?
假设出于扩展和备份原因,您将Avatar文件移动到数据库中,那么该代码将突然转移到存储库中。 存储库是我们立即将其映射到数据库的东西,但它是数据存储的通用术语,也可以存储物理文件。我们不关心存储库如何实现这一点。我们只关心使用业务问题编写业务逻辑,而不必担心基础架构问题。
所以我会将创建和更新您的Avatar的代码移动到您的BLL中,并将处理物理文件的代码移动到您的Repository中。

2
我从未真正考虑过物理文件通过存储库。这很有道理!可能是老习惯了。 - DDiVita
存储文件是您基础设施的一部分,但确实,这是旧习惯 :-) - Wouter de Kort

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接