2011-11-08 246 views
1

试图遵守DRY原则,以下是使多个对象共享通用角色关系表的有效方法。共享相同角色关系表的多个实体

如果我们有以下几种类型(纯粹是为了这个例子创建):

class User 
{ 
    ... 
} 

class Article 
{ 
    ... 
} 

这些对象都需要有对他们定义的角色。因此,角色对于这些对象中的任何一个都不是唯一的。

我的想法是让Repositories在这些对象上执行CRUD操作,还让Role有可能通过服务访问它自己的Repository?

存储库会将UserDTO和ArticleDTO反馈给Builder类,该类将生成必需的Domain对象。在这种情况下:

class User 
{ 
    ... 
    IList<Role> Roles { get; set; } 
    //Other Domain objs/logic 
} 

class Article 
{ 
    ... 
    IList<Role> Roles { get; set; } 
    //Other Domain objs/logic 
} 

角色对象有一个角色表:

ID名称

而且关系表:

的itemId角色ID ITEMTYPE

作用生成器/服务用于将角色附加到域对象可能看起来像这样:

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)); 
    } 
} 

另一种方法是让用户和物品管理他们自己的角色操作并且可能有多个角色关系表例如user_has_roles,article_has_roles

第一种解决方案允许最终用户也修改角色(重命名,添加新角色等),而不会破坏领域模型,而在第二种解决方案中,我不确定如何干净地做到这一点(更新他们通过用户,通过文章?)

+0

貌似很多的精力来跟踪“角色”,几乎没有任何与之相关联的行为。另外,从技术上讲,说用户和文章具有角色'IHaveRoles'或'HasRoles'(对于命名冲突如何)更合适。如果“角色”真的是一个单独的概念,那么可能值得探讨它们是否属于相同的有界环境。 –

+0

谢谢伊夫!我对我最初的建议的结构有了一些想法,并且已经改变了很多。我可能会发布更新以备将来参考。 –

回答

1

如果角色的概念是从用户和文章分开 - 它听起来像是因为它适用于这两个域对象 - 然后我可能会模型是分别像你建议。

我不确定当你说“允许角色被最终用户修改”时你的意思。如果角色是一个单独的概念,他们应该可以拥有自己的域类来表示可以针对角色执行的操作(重命名,删除等)。

而且您的代码段或许应该是这样的(使用仿制药,而不是无效的typeof()语法在上面的代码中):

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)) { ... } 
    } 
} 

我可能也考虑有某种基类的所有可以分配角色的域对象(如果角色用于安全性,那么可能是SecurableEntity或其他),那么您可以在数据库中拥有一个基类表以支持ID的共享标识(以便您可以摆脱itemType Roles表中的列)。或者,您可以使用GUID作为实体ID,这使得许多事情变得更容易。

+0

Hi Dylan,“允许角色由最终用户修改”,这意味着在UI中会有一个表单允许管理员(或指派的角色)更新系统中的角色。 –

0

你的想法听起来不错。我会避免将角色(或更一般的某种授权系统)与文章和用户模型结合在一起。

我不喜欢你的代码是什么静态RoleBuilder。首先:它是静态的,会导致耦合。第二:RoleBuilder不应检索从仓库里面却得到萨姆例如通过例如一些服务推并从这个数据建立模型,角色或只是一个列表。如果让RoleBuilder查询Repo,可以将Builder的责任与查询逻辑联系起来。

另一个问题可能来自你的UserBuilder实施出现。对于抓取单个用户可能没问题,但用该逻辑提取多个用​​户将导致选择N + 1。

0

您的倍数关系表的第二个想法是比较合适的。第一种方法将无法在数据库中维护一个干净的外键。您应该能够从任一实体更新角色,并且将反映在从另一个实体的存储库中获取的下一个角色中。在我看来,通常最好是将参照完整性保留在数据库中,并且将具有外键的表连接到角色表时,它将阻止您执行诸如将用户实体附加到文章时从角色中删除角色的操作实体。虽然第一种解决方案很聪明,但您必须实施一些业务逻辑以确保数据完整性......当ORM可以为您做这件事情时,为什么这种事情会让业务层混乱?

相关问题