实体框架代码中的第一个TpT映射



我正在研究一个复合总系统应用程序,不同的公司可能会添加不同的模块,但只有一个数据库。我的框架中有一个通用的存储库,它是独立于技术的(我的意思是它是基于提供程序的,目前默认的提供程序是EF 4.1)。我分离了包含poco实体的公共层,每个模块在自己的组件中也有不同的实体。现在的问题是实体映射。我没有任何访问我的实体从我的EF供应商项目,因为我不知道未来的模块!那么,如何用通用方法映射实体呢?这可能吗?

我认为的一个解决方案是有一个配置文件和添加实体FullName然后迭代和反映每一个,然后我可以在onmodelcreate(…)方法中添加它们,但当然有一些性能问题。

编辑:首先感谢你的回复,Ladislav。但是还有一些信息要告诉你。

您可以要求每个模块必须包含映射类为它使用的每个新实体。在启动应用程序时您只需使用反射来获取派生的所有类StructuralTypeConfiguration<>(包括实体和复杂的类型),创建这些类型的实例并将它们添加到Configurations中(可以在OnModelCreating中完成)

这将需要一些时间,但它只会发生一次,当上下文是第一次使用。您可以在过程中触发此创建应用程序启动-应用程序只是需要一些时间来启动和运行配置他们需要使用的所有基础设施。

编辑:

我必须在每个模块中引用EntityFramework.dll,这在这种情况下是不合适的。

是的。您希望允许其他开发人员定义他们自己的实体它将由您的核心应用程序持久化。在这种情况下,他们必须使用您选择的持久性框架来告诉您的应用程序吗如何持久化它们的实体。

==>正如我前面提到的,EF不是我唯一的数据提供者!我必须有一些其他DP,如db40的数据提供程序等,所以我不想引用每个提供程序对每个模块的依赖关系……因此,我需要将EF封装在单独的程序集中。

如果使用存储库,每个模块甚至应该包含它自己的用于处理自身实体的存储库——通用存储库不存在。通用存储库是冗余无用的一层只会使您选择的ORM工作更加困难。为了说清楚一点正确实现的存储库模式不是通用的。它是特定的,它为单个实体或聚合根。

==>我可以要求任何可靠的参考吗?!如果只有一个存储库可以满足我的所有需求,为什么我要为每个模块添加一个存储库?哪个是多余的?在我看来,在正确的情况下,使用特定的或通用的代表都是正确的。我的90%的模块有相同的需求从一个存储库,他们都应该有CRUD…

如果你不想在模块中依赖EF,也不要使用EF或者定义您自己的中间映射层,它将被转换在您的应用程序中特定的映射-大量的工作与零附加值。

==>事实上,我试图定义我自己的映射层,因为我需要它在我的应用程序架构。这对我来说不是没有用的。这是我询问如何实现它的唯一原因。我正在寻找最好的解决方案,我希望你能帮我把它交给我:)

另一个选项就是不允许你的模块使用新的实体因为它看起来更像你当前的期望。如果模块开发人员必须为他的实体定义新的数据库表还能够使用持久性并定义两者之间的映射表及其实体

==>好主意,但不适合我的情况;)

我必须在启动时反映每个模块dll,这意味着要反映很多重dll和…还有别的办法吗?

你见过像Photoshop, Visual Studio甚至启动时的MS Office应用程序?你认为是什么当你看到启动画面时发生了什么?应用程序正在初始化它正在加载和初始化其功能和插件。即使服务器应用程序可能需要几分钟才能完全启动。你在建造模块化应用程序(不是组合),因此您必须为此付费要求。

==>是的,我想我看到了一些!例如,如果他们在启动时加载所有的托盘或侧边栏,他们必须雇用我。嘿,亲爱的微软,如果你不知道什么是延迟加载,我可以帮助你提高你的性能:)

如果你不想自己使用反射,你可以使用MEF for构建模块化基础设施。

==>我已经使用Prism和MEF来处理模块化,但只针对模块而不是我的提供商…

这听起来EF不是一个很好的解决方案的企业复合应用程序,对吗?

你没有提出任何不应该提出的企业需求由EF完成。你只是在与你的期望作斗争模块开发人员使用新的实体,但不给他们的能力描述这些实体将如何持久化——但由谁来描述它吗?

==>一个模型或一个中间映射器层,它将在每个模块加载和映射实体,如果EF支持(这不能,因为我知道),我需要像bootstrapper的东西为每个提供者映射实体:)

您不是在构建复合应用程序。复合应用程序获取现有功能(组件、现有应用程序),其中单独工作,并将它们组合成一个新的应用程序。你是构建模块化应用程序,您的核心可以托管其他模块但是,如果没有您的托管基础设施,这些模块无法运行。

==>我不打算讲我的应用程序和它的架构但我认为这些就足够了,你知道这是一个复合/模块化应用程序。

我应该切换到模型第一吗?

模型第一(和EDMX一般)真的不适合你期望,因为在模型第一的情况下,每个模块都需要它的自己的EDMX文件和自己的上下文。

==>但我可以在运行时更改模型和EDMX文件的xml对吗?!

您也不能首先使用代码自动生成数据库因为任何新的模块要么会破坏你的应用程序,要么会破坏EF删除当前数据库

==>谢谢你的建议,虽然我之前就知道了,但我当然会更加注意的。

你可以要求每个模块必须包含它使用的每个新实体的映射类。当您启动应用程序时,您将使用反射来获取从StructuralTypeConfiguration<>派生的所有类(包括实体和复杂类型),创建这些类型的实例并将它们添加到DbModelBuilder中的Configurations集合中(可以在OnModelCreating中完成)。

这将花费一些时间,但它只会在第一次使用context时发生一次。你可以在应用程序启动时触发这个创建——应用程序只需要一些时间来启动和配置它们需要使用的所有基础设施。

编辑:

我必须在每个模块中引用EntityFramework.dll,这在这种情况下是不合适的。

是的。您希望允许其他开发人员定义他们自己的实体,这些实体将由您的核心应用程序持久化。在这种情况下,它们必须使用您选择的持久化框架来告诉您的应用程序如何持久化它们的实体。

如果你使用存储库,每个模块甚至应该包含自己的存储库来处理自己的实体——通用存储库不存在。通用存储库是多余的无用层,它只会使您选择的ORM工作更加困难。明确地说,正确的存储库模式实现不是通用的。它是特定的,它为单个实体或聚合根公开数据访问功能。

如果你不想在模块中依赖EF,要么根本不使用EF,要么定义你自己的中间映射层,它将在你的应用程序中转换为特定的映射——大量的工作和零附加值。

另一个选择是不允许你的模块使用新的实体,因为它看起来更像你当前的期望。如果模块开发人员必须为他的实体定义新的数据库表,他还必须能够使用持久化并定义表和他的实体之间的映射。

我必须在启动时反映每个模块的dll,这意味着要反映很多重的dll…还有别的办法吗?

你见过像Photoshop, Visual Studio甚至MS Office这样的应用程序吗?当你看到启动画面时,你认为会发生什么?应用程序正在初始化——它正在加载和初始化它的功能和插件。即使是服务器应用程序也可能需要几分钟才能完全启动。您正在构建模块化应用程序(而不是复合应用程序),因此必须为该需求付费。

如果你不想自己使用反射,你可以使用MEF来构建模块化的基础设施。

听起来EF不是一个很好的企业复合应用解决方案,对吗?

你没有提出任何EF不应该满足的企业需求。你只是与你的期望作斗争,允许模块开发人员使用新的实体,但不给他们描述这些实体将如何持久化的能力——但谁来描述呢?

您不是在构建复合应用程序。复合应用程序采用单独工作的现有功能(组件、现有应用程序),并将它们组合成一个新的应用程序。您正在构建模块化应用程序,您的核心可以托管其他模块,但这些模块无法在没有您的托管基础设施的情况下运行。

我应该切换到模型第一吗?

模型优先(通常是EDMX)真的不适合你的期望,因为在模型优先的情况下,每个模块都需要自己的EDMX文件和自己的上下文。

你也不能首先使用代码自动生成数据库,因为任何新的模块要么会破坏你的应用程序,要么EF会删除你当前的数据库。

最后编辑,因为这不是讨论区:

EF不是我唯一的数据提供者!我必须有一些其他的DP,比如…

我不知道你为什么那样做,但这是错误的。单个应用程序(甚至是模块化的)应该使用单个提供者(ORM映射器)。如果由于一些遗留代码而有其他数据提供程序,那么就这样吧,但您应该为所有新代码建立单一提供程序策略。否则,您是在与架构过度的应用程序而不是EF作斗争。在这种情况下,你的模块将始终只使用对提供商的单一依赖。

我可以要求任何可靠的参考吗?!为什么每次要添加一个存储库模块的情况下,只有一个存储库可以做我的所有需求?哪个是多余的?

参考经验。有数百个关于存储库和EF的问题。如果您想充分利用EF的优势,通用存储库将不允许这样做,或者它将不得不公开在其他提供程序的实现中不可用的特性。如果您使用存储库只是为了暴露单个实体的CRUD,那么您只是包装了IDbSet已经提供的功能。我理解你正在使用存储库来隐藏你的提供者。

事实上,我正在尝试定义我自己的映射层,因为我需要它在我的应用程序架构。这对我来说不是没有用的。

您将为每个特定于提供程序的映射编写一些自定义映射(可能是XML)和转换器。我不知道你期待什么更好的答案——除了这不是一个好办法。

一个模型或一个中间映射器层,它将在每个模块加载和映射实体中工作,如果EF支持(据我所知不能),我需要像bootstrapper这样的东西为每个提供者映射实体

它不是EF的缺失部分。它完全超出了EF的范围。任何由EF定义的中间层仍然是EF的一部分,不被其他工具支持。EF可以在创建模型时加载实体,但是要加载它们,你必须告诉EF它们的存在以及如何映射它们——这就是我最初的答案所解释的。

我不打算讲我的应用程序和它的架构但我认为这些就足够了,你们知道这是一个复合/模块化应用

可以,但是组合组件没有这些挑战,因为组合应用程序的每个组件都是独立的,可以使用完全不同的持久性。你所面临的挑战是每个模块组件内部的。

但是我可以在运行时改变模型和EDMX文件的xml对吗?

试试。提示:没有公共API在底层操作这个XML,也没有公共API修改加载的模型。可以在加载EDMX之前更改它,但这通常意味着为SSDL、MSL和CSDL编写自定义解析器和xml构建器。您将拥有一组由所有已安装模块更新的映射文件。您还必须编写反向操作来卸载模块并正确地从映射中删除所有功能。任何错误都可能破坏整个应用程序,因为映射将被破坏。我最初的想法是为代码映射加载配置,这将花费您不到一天的时间。建造这个需要多长时间?

如果你想这样做,从你的项目中完全删除EF,并开始使用NHibernate和hbm映射文件。模块开发人员将使用模块逻辑和新实体、数据库表脚本和每个实体的hbm文件创建程序集。模块安装将创建表,将程序集添加到模块位置,并将hbm文件添加到映射拾取目录。你的NHibernate会话将从该目录加载所有映射文件。

最新更新