自定义数据库表的自定义实体构建器

时间:2014-03-05 14:57:21

标签: c# entity-framework .net-4.5 code-first entity-framework-6

我正在使用Entity Framework 6设计多租户应用程序。此应用程序的一个关键要求是允许每个租户拥有自定义表。这意味着一个具有相同名称的表可能在模式之间有所不同。

例如,一个租户可能有一个“人员”表,其中包含:ID,FirstName,LastName,BirthDate。

另一个租户可能有一个“人员”表,其中包含:ID,FirstName,LastnName,BirthDate,FavoriteColor。

当我设计我的模型时,这就是我所拥有的:

public class Person
{
  public int ID { get; set; }

  public string FirstName { get; set; }

  public string LastName { get; set; }

  public DateTime BirthDate { get; set; }
}

这适用于第一个租户,但第二个租户中的自定义列不会被加载。我希望做的是这样的事情:

public class Person : Dictionary<string, object>
{
  public int ID { get; set; }

  public string FirstName { get; set; }

  public string LastName { get; set; }

  public DateTime BirthDate { get; set; }
}

然后编写一个自定义模型映射器/构建器,它将没有匹配属性的表列放入字典集合中。

这有几个问题:

  1. 实体框架创建一个列出所有内容的SELECT语句 模型中的属性/列。不知怎的,我需要更换 列出*以便所有列,甚至是EF不知道的列 关于,回来。

  2. 我需要能够拦截结果集,映射已知的列 到模型属性,并将未知列放入 字典。

  3. 这有可能吗?有没有更好的方法来解决这个问题?

1 个答案:

答案 0 :(得分:3)

我遇到了类似的问题,一个更普通的问题。

在我的应用程序中,最终用户可以定义他的数据对象。在设计时我甚至不知道Person类。这意味着从设计角度将属性添加到我在运行时甚至都不知道的类。 :)

刚开始,忘掉Entity Framework。你试图解决这个问题并不会有太大的影响。我花了一些时间来比较和分析解决方案。好消息:我找到了一个!

我现在正在做的是允许用户指定数据对象的名称以及属性。接下来,我使用CodeDOM根据用户数据生成包含POCO类的程序集。所有类都来自空IDataObject接口。

最后使用反射,我正在加载类并根据用户需求再次使用它们。从空接口继承非常有用,主要有两个原因:

  • 使用反射获取类:我使用接口来获取从中派生的类。 Type.GetType()有助于选择我需要的那个。
  • 我使用的ORM(见下文)使用的是通用方法。我只是在我的方法中添加where T : IDataObject来限制使用。

我使用的ORM是ServiceStack OrmLite。 V4不是免费的,但你仍然可以使用V3(你可以从NuGet获得)。顺便说一句,它是最快的.NET ORM之一。

OrmLite要求的是所插入/更新的对象的类型等等。因为我使用dynamic关键字来保持类型解析到运行时。看看这里:

有关CodeDOM的更多信息:

顺便说一句,我很抱歉没有发布代码示例,这是因为两个原因:规模和雇主IP。

最后,这是我在试图解决这个问题时提出的另一个问题。它可能会有所帮助。

抱歉,我忘了提到为每个最终用户完成了程序集生成。如果要扩展现有类型(因为将生成新的程序集版本),这可能会导致应用程序重新启动。 OrmLite负责使用CreateTable<T>(true)方法扩展表。