2

我将实体框架用于一个相当简单的问题跟踪应用程序。我想通过添加其他属性为用户提供扩展“问题”实体的能力,例如:

  • 数字字段
  • 文本字段(简单或富文本)
  • 不同的列表(多选\单选)
  • 布尔属性

我想到了两种完成任务的方法:

可扩展数据库方法

这种方法是公正的想法,我不知道如何使用实体框架来实现,所以我非常希望得到你的帮助。这是基本概念:

  1. 创建一个名为 IssueExtendedFields 的表,其中每个字段都有一条记录,描述它的类型和名称,可能还有其他属性。
  2. 创建另一个名为 IssueFieldOptions 的表,该表将保存每个“列表类型字段”的选项列表
  3. 最终表名为 IssueExtendedFieldValues,它将为用户创建的每个自定义字段保存一个具有特定命名约定的列,并为每个问题保存一个外键。

现在我只是不知道如何实现第三步,因为使用实体框架并且有从表中生成的 EF 实体对象(首先是 DB)所以理论上每个新列都必须重新映射和重新编译 DAL项目。

你有什么其他的建议?

字典法

这种方法我知道如何实施

  1. 创建一个名为 IssueExtendedFields 的表,其中每个字段都有一条记录,描述它的类型和名称,可能还有其他属性。
  2. 创建另一个名为 IssueFieldOptions 的表,该表将保存每个“列表类型字段”的选项列表
  3. 最后一个名为 IssueExtendedFieldValues 的表将保存输入到系统中的每个“字段 - 值”对的记录

但它有许多缺点(如果你知道如何克服它们,请发布)。

  1. 用户添加的每个新属性只是另一条记录,将每个实体存储的数据量乘以 X,其中 X 是属性的数量,我看到大量问题进入系统并创建一个单独的表,该表将再容纳 10 条记录每个问题都会产生大量查询,需要大量内存。
  2. 除了可预见的内存问题,我将不得不创建动态“数据透视”,如报告和视图,以允许用户再次生成自定义属性报告,并且当您处理大量数据时,“数据透视”查询将花费更多时间.
4

2 回答 2

3

我知道这个问题已经很老了,但是没有什么可以阻止您在运行时使用您的数据库架构在那个特定时刻构建您的 EF 数据模型。由于您的大部分数据模型都是静态的,因此增加的复杂性被本地化为在运行时可以更改的实体:

  1. 当您在运行时向数据库添加列时,您也需要将属性添加到相应的类型。这意味着您的类型是在运行时构造的。您可能会在运行时创建具有附加属性的派生类型(或实现某些接口),以便您的编译时代码具有合理的类型以用于其他情况。这可以使用Reflection.Emit来完成。

  2. 每当架构更改时,您都需要在运行时动态构建 EF 映射。您可以使用 EF Code First 来做到这一点。如果您的映射符合正常的 EF Code First 约定,那么除了确保将运行时类型添加到映射中之外,您无需在此处执行任何操作。否则,您必须实现代码,在运行时为您的附加属性确定和配置必要的映射。

  3. 任何使用附加属性的查询都需要在运行时动态构建。这意味着构建成员访问表达式以在您的 LINQ 查询中使用。类似地,访问仅在运行时知道的附加属性的值将需要反射

您对第二种方法保持警惕是正确的,这种方法更广为人知的是Entity-Attribute-Value (EAV) data modeling。这种方法有许多缺点,其中最重要的是连接/查询复杂性增加以及缺乏外键支持。但是,由于 EAV 模型是在编译时声明的,因此可以说它更容易实现。

或者,您可以考虑使用专门用于具有灵活模式的实体的另一个数据存储,例如文档数据库

于 2014-11-12T23:41:49.927 回答
0

因此,理论上每个新列都必须重新映射和重新编译 DAL 项目。

你回答了你自己的问题:) EF 使用固定的数据库模式,所以第一个选项无论如何都不是一个选项。

于 2013-02-22T11:25:13.983 回答