C# 共享同一角色关系表的多个实体
尝试遵循DRY原则,以下是让多个对象共享一个公共角色关系表的有效方法 如果我们有以下类型(仅为本例创建): 这两个对象都需要针对它们定义角色。因此,角色对于这些对象中的任何一个都不是唯一的 我的想法是让存储库对这些对象执行CRUD操作,但也让角色拥有自己的存储库(可能通过服务访问) 存储库将UserDTO和ArticleDTO提供给一个生成器类,该类将生成必要的域对象。在这种情况下:C# 共享同一角色关系表的多个实体,c#,asp.net-mvc,database,domain-driven-design,dns,C#,Asp.net Mvc,Database,Domain Driven Design,Dns,尝试遵循DRY原则,以下是让多个对象共享一个公共角色关系表的有效方法 如果我们有以下类型(仅为本例创建): 这两个对象都需要针对它们定义角色。因此,角色对于这些对象中的任何一个都不是唯一的 我的想法是让存储库对这些对象执行CRUD操作,但也让角色拥有自己的存储库(可能通过服务访问) 存储库将UserDTO和ArticleDTO提供给一个生成器类,该类将生成必要的域对象。在这种情况下: class User { ... IList<Role> Roles { get;
class User
{
...
IList<Role> Roles { get; set; }
//Other Domain objs/logic
}
class Article
{
...
IList<Role> Roles { get; set; }
//Other Domain objs/logic
}
另一种方法是让用户和文章管理他们自己的角色操作,并且可能有多个角色关系表,例如用户有角色,文章有角色
第一个解决方案允许最终用户也修改角色(重命名、添加新角色等),而不会破坏域模型,而在第二个解决方案中,我不知道如何干净地做到这一点(通过用户、通过文章更新它们?)如果角色的概念与用户和文章是分开的——听起来是这样的,因为它同时适用于这两个域对象——那么我可能会像你建议的那样单独建模 我不知道你说“允许最终用户也修改角色”是什么意思。如果角色是一个单独的概念,那么它们可能应该有自己的域类来表示可以对角色执行的操作(重命名、删除等) 此外,您的代码段可能如下所示(使用泛型而不是上述代码段中的无效typeof()语法):
静态类RoleBuilder{
静态IEnumerable获取(int-id){
开关(类型(T)){…}
}
静态布尔保存(IEnumerable角色,int-id){
开关(类型(T)){…}
}
}
我也可能考虑为所有可以分配角色的域对象设置某种基类(如果角色用于安全,然后可能是安全实体或某物),那么在DB中可以有一个基类表来支持ID的共享身份(这样就可以摆脱角色表中的ItType列)。. 或者,您可以只使用实体ID的GUID,这使很多事情变得更容易。
如果角色的概念与用户和文章是分开的,听起来像是这样,因为它适用于这两个域对象,那么我可能会像您建议的那样分开建模 我不知道你说“允许最终用户也修改角色”是什么意思。如果角色是一个单独的概念,那么它们可能应该有自己的域类来表示可以对角色执行的操作(重命名、删除等) 此外,您的代码段可能如下所示(使用泛型而不是上述代码段中的无效typeof()语法):静态类RoleBuilder{
静态IEnumerable获取(int-id){
开关(类型(T)){…}
}
静态布尔保存(IEnumerable角色,int-id){
开关(类型(T)){…}
}
}
我也可能考虑为所有可以分配角色的域对象设置某种基类(如果角色用于安全,然后可能是安全实体或某物),那么在DB中可以有一个基类表来支持ID的共享身份(这样就可以摆脱角色表中的ItType列)。. 或者,您可以只使用GUID作为实体ID,这使很多事情变得更简单。
您的想法听起来不错。我避免将角色(或更一般的一些授权系统)与文章和用户模型耦合 我不喜欢你的代码是静态RoleBuilder。第一:它是静态的,导致耦合。第二:RoleBuilder不应该从存储库中检索任何内容,而是获取一些服务推送的实例,例如,构建角色模型或仅从这些数据中获取一个列表。如果您让RoleBuilder查询回购协议,您将生成器的责任与查询逻辑结合起来UserBuilder实现可能会产生另一个问题。对于获取单个用户,这可能是正常的,但是获取具有该逻辑的多个用户将导致选择N+1 你的主意听起来不错。我避免将角色(或更一般的一些授权系统)与文章和用户模型耦合 我不喜欢你的代码是静态RoleBuilder。第一:它是静态的,导致耦合。第二:RoleBuilder不应该从存储库中检索任何内容,而是获取一些服务推送的实例,例如,构建角色模型或仅从这些数据中获取一个列表。如果您让RoleBuilder查询回购协议,您将生成器的责任与查询逻辑结合起来
UserBuilder实现可能会产生另一个问题。对于获取单个用户,这可能是正常的,但是获取具有该逻辑的多个用户将导致选择N+1 您关于多个关系表的第二个想法更合适。使用第一种方法将无法在数据库中维护干净的外键。您应该能够从任何一个实体更新角色,它将反映在另一个实体的存储库的下一个get中。在我看来,通常最好将引用完整性保留在数据库中,并且由于两个联接表都具有角色表的外键,这将阻止您在用户实体附加到项目实体时从用户实体中删除角色等操作。虽然第一个解决方案很聪明,但您必须实现一些业务逻辑以确保数据完整性。。。当ORM可以为你做的时候,为什么要用这种东西来扰乱你的业务层呢?你对多重关系的第二个想法
class User
{
...
IList<Role> Roles { get; set; }
//Other Domain objs/logic
}
class Article
{
...
IList<Role> Roles { get; set; }
//Other Domain objs/logic
}
static class RoleBuilder
{
IEnumerable<Role> Fetch(int id, typeof(obj))
{
//fetch from RoleRep
}
bool Save(IEnumerable<Role>, int id, typeof(obj))
{
//save through role rep
}
}
public static UserBuilder
{
public User FetchUser(int id)
{
//map userDTO to user
var user = map...
//populate roles
if(user != null)
user.Roles = RoleBuilder.Fetch(id, typeof(user));
}
}
static class RoleBuilder {
static IEnumerable<Role> Fetch<T>(int id) {
switch(typeof(T)) { ... }
}
static bool Save<T>(IEnumerable<Role> roles, int id) {
switch(typeof(T)) { ... }
}
}