【问题标题】:.Net architecture Clean Architecture question on Persistence layer and InternalsVisibleTo.Net 架构关于持久层和 InternalsVisibleTo 的清洁架构问题
【发布时间】:2021-07-23 20:46:39
【问题描述】:

假设,我有一个具有只读 Id 属性的实体,例如:

public int Id { get; }

然后我有一个持久层,它实现实体存储库并在实体存储到 db 时分配新的 Id 值:

public async Task AddToDb(MyEntity ent) { ... };

现在,这个方法可以通过读取从 Db 中返回一个实体,但我不喜欢发出另一个网络请求(在这种情况下没有并发)。所以我最好将新的 Id 分配给传递的实体。但是Id 是只读的。我正在考虑使用InternalsVisibleTo 属性使持久层对域层“友好”。

好吧,这似乎有点老套,我知道数据库应该是事实的来源。还有其他选择吗?我在做一些完全不必要/错误的事情吗?

【问题讨论】:

  • 实体和持久层是否在两个不同的程序集中?否则,InternalsVisibleTo 将无济于事,您只需添加一个内部设置器(对于建议的方法,您无论如何都需要这样做)
  • 是的,它们位于不同的程序集中。是的,我使用了InternalsVisibleTo 并使用了内部设置器。

标签: c# .net architecture


【解决方案1】:

除了使用 InternalsVisibleTo 之外,我想到的几个可能的选项是:

  1. 您可以利用 C#9 中引入的 init 访问器来做您需要的事情吗?

    public int Id { 获取;在里面; }

这将允许您将属性保持为只读,但您可以在对象初始化时分配它。

  1. 遵循更多的 CQRS 方法并具有“分离的数据持久性模型”和“数据视图模型”,并从“创建新对象视图模型”中省略 id 属性,使持久性模型中的 id 属性可设置(或作为前面提到的 initable),然后在实际提交到数据库之前从持久层返回 id:

在面向外部的项目中(视图或 API 或其他)

public MyEntityViewModel()
{ 
  string SomeProperty { get; set;}
}

然后在持久层

public MyEntity()
{ 
   public int Id { get; init; }
   string SomeProperty { get; set;}
}

public async Task<int> AddToDb(MyEntityViewModel ent) 
{
   var newEnt = new MyEntity(){ Id = 1234 };
   
   //map the contents of the ViewModel to the peristance Model
   newEnt.SomeProperty = ent.SomeProperty;

   ///code to commit to DB.

   return newEnt.Id;
};

关于每个模型的位置、哪个组件应该负责映射等,这里可以进行各种讨论,但我希望这能传达总体思路。

  1. 使 Id 属性可设置,然后在公共异步任务 AddToDb(MyEntity ent) 中使用由持久层确定的值简单地覆盖它。这可以说是最简单的选项,它允许您对持久层进行最终控制,而无需执行大量繁琐的逻辑。

【讨论】:

  • 是的,部分同意。 1) 然后构造函数将有一个 id 作为参数,这是我想避免的事情,所以 Persistence 层之外的任何人都不允许分配一个 Id 2) 再次,我的目标是不允许任何使用此实体的开发人员分配道具来自 db 3) 持久层需要了解 ViewModels,这在 IMO 上一点都不好 无论如何,这是一个很好的答案!谢谢。
猜你喜欢
  • 2020-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-22
  • 2019-05-30
  • 2011-04-12
  • 1970-01-01
  • 2010-10-21
相关资源
最近更新 更多