我正在使用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; }
}
然后编写一个自定义模型映射器/构建器,它将没有匹配属性的表列放入字典集合中。
这有几个问题:
实体框架创建一个列出所有内容的SELECT语句 模型中的属性/列。不知怎的,我需要更换 列出*以便所有列,甚至是EF不知道的列 关于,回来。
我需要能够拦截结果集,映射已知的列 到模型属性,并将未知列放入 字典。
这有可能吗?有没有更好的方法来解决这个问题?
答案 0 :(得分:3)
我遇到了类似的问题,一个更普通的问题。
在我的应用程序中,最终用户可以定义他的数据对象。在设计时我甚至不知道Person
类。这意味着从设计角度将属性添加到我在运行时甚至都不知道的类。 :)
刚开始,忘掉Entity Framework。你试图解决这个问题并不会有太大的影响。我花了一些时间来比较和分析解决方案。好消息:我找到了一个!
我现在正在做的是允许用户指定数据对象的名称以及属性。接下来,我使用CodeDOM根据用户数据生成包含POCO类的程序集。所有类都来自空IDataObject
接口。
最后使用反射,我正在加载类并根据用户需求再次使用它们。从空接口继承非常有用,主要有两个原因:
Type.GetType()
有助于选择我需要的那个。where T : IDataObject
来限制使用。我使用的ORM是ServiceStack OrmLite。 V4不是免费的,但你仍然可以使用V3(你可以从NuGet获得)。顺便说一句,它是最快的.NET ORM之一。
OrmLite要求的是所插入/更新的对象的类型等等。因为我使用dynamic
关键字来保持类型解析到运行时。看看这里:
有关CodeDOM的更多信息:
顺便说一句,我很抱歉没有发布代码示例,这是因为两个原因:规模和雇主IP。
最后,这是我在试图解决这个问题时提出的另一个问题。它可能会有所帮助。
抱歉,我忘了提到为每个最终用户完成了程序集生成。如果要扩展现有类型(因为将生成新的程序集版本),这可能会导致应用程序重新启动。 OrmLite负责使用CreateTable<T>(true)
方法扩展表。