如果EAV是邪恶的,那么动态值的用途是什么?

我需要创建一个数据库,其中Accountgroup表将具有动态字段,以便Accounts可以在需要时输入这些动态字段值。 它可能并不重要,但我正在使用C#与EF和Linq。

这对我来说很难,因为我从来没有做过这样的事情,因为我做了我的研究,每个人都说EAV系统太可怕了, 你应该设计得不同 ,问题是之后没有人告诉 – 怎么样?

所以也许你可以帮助我,告诉我如何在不做EAV的情况下实现类似的东西?

这就是我到目前为止所拥有的。

在此处输入图像描述

经验法则的问题在于它们很快就会从“做X通常是一个坏主意”到“永不做X ”。

EAV 通常是一个坏主意,因为它在许多方面违背了关系模式的目的,因此它消除了关系DBMS的许多特性和优势,以及构建在RDBMS上的其他技术,例如ORM,如Entity Framework。

但是,有一些设计问题,RDBMS并不适合。 有一些非常不合适,必须发明一种全新的技术(例如NoSQL DB,如MongoDB)。

有时EAV可能是一组不完美选项留给你的最佳选择。 如果你不能(不能)知道你的架构是什么,那么EAV可能是你的最佳选择。 如果您的架构结果不重要,则尤其如此。 例如,考虑一个在线产品目录,其中有大量产品列表,每个产品都有一些function。 您无法提前预测哪些产品具有哪些function。 最后,您对产品function的唯一做法是将它们转储到“feature:value”列表中。 这种情况下架构并不是特别强大,因此用EAV击败它并不是特别具有破坏性。

最重要的是要了解您的设计选择将对您的能力和操作做些什么。 所有设计都是权衡。 关键是要有意识地进行权衡。 而不是“EAV是邪恶的”,而是改为:“EAV是一把装满枪的枪,确保你知道你指着它的脚。”

那么,在最简单的层面上,只需将值添加为列 ; 也许在数据库中使用稀疏列支持 ,这样它就不会产生太大的影响。 这避免了EAV和内部平台效应,并且意味着您将值存储为常规的类型值

EAV不是“邪恶的” – 当其他解决方案可能更合适时,它有时会被误用。

如果您的属性是真正动态的,并且您希望避免动态添加列1 ,那么EAV是合适的。


1例如,为了避免锁定桌子,或者因为您选择的ORM不能很好地使用它,或者因为它们太多了。

当您开始使用EAV字段进行报告或BI时,您将需要自己拍摄。

  1. 使用XML字段。 大多数数据库都具有良好的XML支持,XPath查询和索引。

  2. 为租户的用户设计字段创建新架构。 让用户使用该模式执行他们想要的操作(在合理范围内)。

例如

 create table account_group ( id primary key references real_schema.accountgroup(id), super_important_note_field text not null ); 

是的,您可以跨模式执行外键。