标记多个实体的架构

时间:2016-01-29 22:12:08

标签: entity-framework database-schema tagging

忍受我......

我正在实现一个具有多个不相关类的应用程序,这些类需要共享一个共同的标记机制。这应该允许(除其他外)跨多个实体按标签搜索;甚至在其他无关的项目中通过共享标签创建软关系。

使用Entity Framework Code First时,到目前为止我找不到一个我认为可以接受的解决方案。下面是我尝试过的设计尝试的描述:

假设: “标签”实体。 “条款”实体,可以加标签。 “发布”实体,可以标记。 “其他”类型:只能标记与之前版本无关的任何其他类型。

选项1:一个包含多个外键的常见“EntityTag”类。

该方法包括创建一个“EntityTag”junciton-entity,它生成一个“EntityTags”联结表,并且每个可以标记的实体都有多个可以为空的外键。

优点: - 单一类型简化了进一步的开发(UI,搜索查询等)

缺点: - 糟糕的数据库设计 - 需要强化代码中的DB约束(至少选择一个值,等等) - SaveChanges和其他EF方法需要清理孤立的EntityTags

选项2:每种关系一种类型。

此方法每个联结表/实体需要一种类型。有一个带有TagId和Tag导航属性的基本“EntityTag”类型。 例如:“ArticleTag”,“PostTag”,“OtherTag”等

优点: - 看起来像一个更好的规范化数据库设计 - 代码

中不需要清理或约束强化

缺点: - 难以进行跨实体查询,因为您需要单独引用联结表并将它们与父项相关联 - 使用视图也很痛苦,因为尝试使用基类有点奇怪,因为集合转换和方差 - 协方差 - 我不得不重构服务,存储库等来定义泛型上的标记实体的类型,这看起来也很麻烦(而且很可怕)

选项3:可以标记的任何实体的基类(超类型/子类型)

此方法考虑使基本“实体”类仅包含Id(可能是审计列),并且具有继承自此实体类型的任何其他实体类型。 例如:文章 - >实体,后 - >实体等 然后有一个“EntityTag”联结类型/表,它将任何实体与标签相关联。

优点: - 简化语法和编码(至少与选项2相比!) - 基类可用于执行常见审计(与标记无关,但有用) - 非常简单的查询,因为任何类型都可以使用其常见的“EntityTags”导航属性,如果需要应用过滤 - 使用Views也非常简单,因为它们都处理EntityTag

缺点: - 随着解决方案的发展,对这些影响感到害怕。 - 生成的SQL查询变得更加复杂,因为它们需要与SuperType连接,然后与标签连接 - 从纯域驱动(甚至是对象建模)的角度来看,类型之间确实没有任何关系。这是由持久层强制执行的,这与正确的DDD相反。 - 在某些情况下,BlogPost和NewsArticle之间可能存在共享关系。我们假设例如“文件”。每个BlogPost和NewsArticle都可以有文件。在这种情况下,只有那两种类型可以拥有它们,但是为了继续使用基类方法,那么共享某些内容的每两种类型都需要具有基类,这根本不可能。 我想过用“受保护的内部”做一些魔法,并且只有在实体意图拥有它们时才公开属性。 这将最终具有“上帝”基类,然后允许在子类上“附加/公开”事物。这有一些设计气味......

选项4:我要求您提供的

这对我来说真的是“继承VS组合”的古老冲突。 我希望Entity Framework能够通过接口(ITaggable,IFileCollector等)解释我的Composition,并将其转换为DB Schema。 通过限制基类和继承,它会强制一些不自然的关系,并为Domain层增加额外的不必要的复杂性(以及更少的正确性)。

另一种方法是将Persistence模型与Domain模型分离,具有2组独立的实体。我期待EF Code First提供一种不分离它们的方法,只需要一个模型。

如果你到目前为止读过,谢谢你的时间!

0 个答案:

没有答案