本文介绍了Dynamic\用户可扩展实体使用实体框架的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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




  • 数字字段

  • 文本字段(简单或富文本)

  • 不同的列表(multiple \ single select)

  • 布尔属性



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



可扩展数据库方法



这是方法只是想法,我不知道如何实现使用实体框架,所以我会非常像你的帮助
这是基本的概念:


  1. 创建一个名为IssueExtendedFields的表,每个字段都有一个记录它的类型和名称以及可能的其他属性。

  2. 创建另一个名为IssueFieldOptions的表,其中将包含每个列表类型字段的选项列表

  3. 而最后一张桌子放了一个将持有Colu的IssueExtendedFieldValues mn与用户创建的每个自定义字段的特定命名约定和每个问题的外键。

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

您还有其他建议吗?



字典方法



这个方法我知道如何实现


  1. 创建一个名为IssueExtendedFields的表,它将为每个描述它的类型和名称以及可能的其他属性。

  2. 创建另一个名为IssueFieldOptions的表,其中将包含每个列表类型字段的选项列表

  3. 最后一个表名为IssueExtendedFieldValues的表将为每个输入到系统中的Field-Value对保存一个记录

但是它有许多缺点(如果你看到如何过来,请发贴)。


  1. 用户添加的每个新属性只是另一个记录将每个实体存储的数据量乘以X,其中X是属性数,我看到大量的问题进入该系统和创建一个单独的表,每个问题将持有10个更多的记录将产生巨大的查询将需要大量的内存。

  2. 除了预见的内存问题,我将不得不创建动态数据透视(如报告和视图),以便用户再次生成报表的自定义属性,当处理大量数据时,数据透视查询将花费更多时间。


解决方案

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


  1. 列在运行时到您的数据库,您也需要添加属性到您的对应类型。这意味着您的类型是在运行时构建的。潜在地,您将在运行时创建一个派生的类型(或实现一些接口)附加属性,以便您的编译时代码具有合理的类型。这可以使用。


  2. 当您的架构更改时,您需要在运行时动态构建EF映射。您可以使用EF Code First进行此操作。如果您的映射符合正常的EF Code First约定,则除了确保将运行时类型添加到映射之外,您还需要执行此操作。否则,您必须实现代码,在运行时确定并配置其他属性的必要映射。


  3. 使用其他属性的任何查询都需要在运行时被动态构造。这意味着可用于您的LINQ查询。类似地,访问仅在运行时已知的附加属性的值将需要。


你是否正确地警惕第二种方法,被广泛称为。这种方法有很多缺点,其中最重要的还是增加了连接/查询的复杂性以及缺少外键支持。然而,由于EAV模型在编译时被声明,所以可以说更容易实现。



或者,您可以考虑使用另一个数据存储专门为具有灵活的模式,例如。


I use entity framework for a fairly simple issue tracking app.I would like to provide the user the capability to extend the "Issue" entity by adding additional properties such as:

  • Number fields
  • Text fields (simple or rich text)
  • Different lists (multiple\ single select)
  • Boolean property

I thought of two ways to accomplish the task:

Extendable Database Approach

This is approach is just and idea and i don"t know how to implement using Entity Framework so i would very much like your help.Here is the basic concept:

  1. Create a table called IssueExtendedFields that will have a record for each field describing it's type and name and maybe other properties.
  2. Create another table called IssueFieldOptions that will hold a list of options for each "list type field"
  3. And the final table caled IssueExtendedFieldValues that will hold a Column with a specific naming convention for each custom field created by the user and a foreign key for each issue..

Now i just don't know how to implement the 3rd step because is use entity framework and there are EF entity objects that are generated out of the tables (DB first) so each new column will theoretical have to re-map and recompile the DAL project.

Do you have any other suggestions?

Dictionary Approach

This approach I know how to implement

  1. Create a table called IssueExtendedFields that will have a record for each field describing it's type and name and maybe other properties.
  2. Create another table called IssueFieldOptions that will hold a list of options for each "list type field"
  3. And the final table called IssueExtendedFieldValues that will hold a record for each "Field - Value" pair that is entered into the system

But it suffers from numerous drawbacks (if you see how to over come them please post).

  1. Every new property the user adds is just another record multiplies the amount of data stored for each entity by X where X is the number of properties, I see big numbers of issues going into the system and creating a separate table that will hold 10 more records for each issue will generate huge queries that will require a lot of memory.
  2. On top of the foreseen memory problems I will have to create Dynamic "Pivot" like reports and views to allow the user generating reports again the custom properties, and when you deal with huge amount of data the "Pivot" query will take even more time.
解决方案

I know this question is pretty old, but there's nothing to prevent you from building your EF data model at runtime with whatever your database schema is at that particular moment. Since most of your data model is static, the added complexity is localized to whichever entities can change at runtime:

  1. As you add columns to your database at runtime, so too will you need to add properties to your corresponding type. This means your type is constructed at runtime. Potentially you would create a derived type (or implement some interface) at runtime with the additional properties so that your compile-time code would have a reasonable type to work with otherwise. This can be accomplished using Reflection.Emit.

  2. You'll need to dynamically build your EF mappings at runtime whenever your schema changes. You can do this with EF Code First. If your mappings fit normal EF Code First conventions, there's nothing more you need to do here other than to make sure your runtime types are added to the mapping. Otherwise, you'll have to implement code which determines and configures the necessary mappings for your additional properties at runtime.

  3. Any queries which utilize the additional properties will need to be dynamically constructed at runtime. This means building member access expressions to use in your LINQ queries. Similarly, accessing the values of additional properties only known at runtime would require reflection.

You're correct to be wary of your second approach, which is more widely known as Entity-Attribute-Value (EAV) data modeling. There are a number of downsides to this approach, not the least of which are increased joins / query complexity and lack of foreign key support. However, since the EAV model is declared at compile-time, it is arguably easier to implement.

Alternatively, you might consider using another data store specifically for entities which have a flexible schema, such as document databases.

这篇关于Dynamic\用户可扩展实体使用实体框架的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 01:23