在运行时修改ORM模型

时间:2012-07-02 06:21:55

标签: c# entity-framework orm

关于这个主题已经进行了很多讨论(Modifying an Entity Framework Model at Run-Time),但到目前为止我还没有找到一个很好的解决方案。我们目前有一个使用EF 4.0构建的模型,需要允许客户向各种表添加自定义字段。我们目前用一些描述新属性的通用表解决了这个问题,但我们发现解决方案效果不佳。

有没有人知道将数据库动态添加到数据库并更新ORM以在运行时反映这一点的好方法?

1 个答案:

答案 0 :(得分:2)

在运行时更新EF以反映数据库中的更改没有好的,好的或可管理的方法。如果你真的有一个必须在运行时更改的数据库,EF对你来说不是一个好工具。 EF是强类型的 - 对数据库的每次更改不仅必须反映在映射中,还应反映在用于加载和保存数据的实体类中。

在运行时更改实体类总是转到运行时发出IL代码的区域。如果您通过动态模块和动态实体类型创建动态程序集的过程,您将面临许多新的挑战:

  • 您不会更改现有类型 - 每次用户添加或删除某些属性时,您都会生成新类型。
  • 新类型生成为重建上下文的元数据工作空间带来了新的性能成本。如果在服务器上使用它,还必须确保正确同步。另一个问题是旧类型的所有现有实例(在添加或删除属性之前)现在对于EF上下文的新实例是未知的,并且不能被持久化。如果您想要保留它们,您也需要具有旧元数据工作空间的EF上下文实例。
  • 你的很多代码可能会使用dynamic而不是真正的类型=没有编译时检查。直接与EF交互时,继承和接口将无用,因为必须映射继承(您不需要它),并且EF不接受接口。
  • 新类型在设计时未知 - 您无法将其用于设计时代码和编译。
  • EF不喜欢dynamicExpandoObject,因为它使用反射进行映射 - >在运行时,您的动态实例必须是正确的类型,否则反射将无效。
  • 如何为动态类型编写查询?查询始终从为具体类型创建的DbSetObjectSet的通用实例开始 - 您必须能够动态地创建这些实例。通用参数必须是映射到当前上下文的类型 - dynamic在这种情况下不会有帮助,因为它不是映射类型。
  • .NET对于这种情况有一个很好的行为。它无法卸载组件。因此,每次生成新类型时,您都会加载旧时间。

您是否仍想在运行时更改EF?您当前的方法是正确的。只需调整它以获得更好的性能,但要注意这些要求总是伴随着性能成本 - 特别是对于EF。

或者使用链接表中提到的最后一种方法 - 直接在主实体中固定数量的预定义自定义字段。