复合应用程序中的实体框架代码优先 TpT 映射

发布于 2025-01-02 19:10:11 字数 3166 浏览 6 评论 0原文

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

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

编辑: 首先感谢您的回复拉迪斯拉夫。 但还有一些更多信息供您参考。

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

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

编辑:

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

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

==> 正如我之前提到的,EF 不是我唯一的 DataProvider!我必须有一些其他 DP,例如 DB4O 的数据提供程序等,因此我不想引用每个提供程序对每个模块的依赖项...因此我需要将 EF 封装在单独的程序集中

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

==> 请问有可靠的参考吗?!如果只有一个存储库可以满足我的所有要求,为什么要为每个模块添加一个存储库?哪个是多余的? 在我的观点中,使用特定或通用代表在正确的情况下都是正确的。我的模块中 90% 的存储库具有相同的要求,并且所有模块都应该具有 CRUD ...

如果您不希望模块中存在 EF 依赖关系,则根本不要使用 EF 或定义您自己的将被转换的中间映射层 到应用程序中的特定映射 - 大量工作为零 附加值。

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

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

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

我必须在启动时反映每个模块 dll,这意味着要反映很多繁重的 dll,并且......还有其他想法吗?

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

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

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

==>我已经在使用 Prism 和 MEF 来处理模块化,但仅适用于不适合我的提供商的模块...

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

您没有提出任何不应该提出的企业需求 由 EF 完成。你只是与你的期望作斗争,以允许 模块开发人员可以使用新实体,但不赋予他们以下能力: 描述这些实体将如何被持久化 - 但谁来描述 是吗?

==> 如果 EF 支持(据我所知不能),则将在每个模块加载和映射实体中工作的模型或中间映射器层我需要每个提供程序的引导程序之类的东西来映射实体:)

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

==>我不会就我的应用程序及其架构进行演讲,但我认为仅此而已就足以让您知道这是一个复合/模块化应用程序......

我应该切换到模特第一?!!

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

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

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

==> 感谢您的建议,虽然我以前就知道,但我当然会更加关注它。

I'm working on a composite total system application which different companies may add different modules but there is only one database.I have a Generic repository in my framework which is technology independent (I mean it's provider base and for now the defult provider is EF 4.1 ).I have seprated common layer which contains poco entities and there is also different entities per module in their own assemblies.
Now the problem is the entities mapping.I don't have any access to my entities from my EF provider project as I don't know the future modules ! so how can I map my entities in a generic approach? Is it possible?

One solution that I think is having a config file and adding entities FullName then ieterating and reflecting each one and then I can add them in OnModelCreat(...) method but ofcourse there is some performance concerns.

Edit:
Firstly thanks for your reply Ladislav.
But there is some more info for you.

You can make a requirement that each module must contain mapping
classes for every new entity it uses. When you start the application
you will just use reflection to get all classes derived from
StructuralTypeConfiguration<> (includes both entities and complex
types), create instances of these types and add them to Configurations
collection in DbModelBuilder (can be done in OnModelCreating).

It will take some time but it will happens only once when context is
used for the first time. You can trigger this creation during
application start - applications simply need some time to start and
configure all infrastructure they need to use.

Edit:

I have to reference EntityFramework.dll in every module which is not suitable in this case.

Yes. You want to allow other developers to define their own entities
which will be persisted by your core application. In such case they
must use your persistence framework of choice to tell your application
how to persist their entities.

==> as I mentioned before, EF is not my only DataProvider ! I have to have some other DP such as a dataprovider for DB4O and etc so I don't want to reference each provider's dependencies to each module ... therefore I need to encapsulate EF in a separate assembly

If you use repositories each module should even contain its own
repositories for working with its own entities - generic repository
doesn't exists. Generic repository is redundant useless layer which
only makes work with ORM of your choice much harder. To make it clear
- correct implementation of repository pattern is not generic. It is specific and it expose data access functionality for single entity or
aggregate root.

==> may I ask for any reliable ref ?! Why should I add one repository per module in case only one repository can do all of my requirements? which is redundant ?
In my oppenion using specific or generic rep are both correct in a correct situation.90% of my modules has same requirements from a repository and all of them should have CRUD ...

If you don't want EF dependency in modules either don't use EF at all
or define your own intermediate mapping layer which will be converted
to specific mapping in your application - a lot of work with zero
added value.

==> In fact I'm trying to define my own mapping layer because I need it in my app architecture.it is not useless for me.This was the only reason that I asked how to implement it.I'm looking for the best solution and I hope you could help me to hand on it :)

Other option is simply not allowing your modules to use new entities
because it looks more like your current expectation. If module
developer must define new database tables for his entities he must
also be able to work with persistence and define mapping between
tables and his entities.

==> Good Idea but not suitable for my case ;)

I have to reflect each module dll at startup which means lots of heavy dll's to be reflected and ... is there any other Idea?

Have you ever seen applications like Photoshop, Visual Studio or even
MS Office applications during their startup? What do you think is
happening when you see splash screen? Application is initializing - it
is loading and initializing its features and plugins. Even server
application can need minutes to be fully started. You are building
modular application (not composite) so you must pay for that
requirement.

==> Yeah I think I saw some of them ! If they are loading for example all the pallets or sidebars at startup they have to employ me .Hey dear microsoft if you don't know what is the defer loading I can help you to improve your performance :)

If you don't want to use reflection yourselves you can use MEF for
building modularized infrastructure.

==>I'm already using Prism and MEF for handling modularity but only for modules not for my providers...

It sounds that EF is not a good solution for enterprise composite app right?

You didn't propose any enterprise requirement that shouldn't be
fulfilled by EF. You just fights with your expectations to allow
module developers to use new entities but don't give them ability to
describe how these entities will be persisted - but who will describe
it?

==> A model or a intermediate mapper layer which will work in each module load and map the entities if the EF support (which can't as I know) I need something like bootstrapper for each provider to map the entities :)

You are not building composite application. Composite application
takes existing functionality (components, existing applications) which
works separately and composite them to a new application. You are
building modular application where your core can host another modules
but those modules cannot run without your hosting infrastructure.

==>I'm not going to give lecture about my app and its architecture but I think just this much is enough that you know this is a composite/modular application ...

Should I switch to Model First?!!

Model first (and EDMX generally) is really not suitable for your
expectations because in case of model first each module will need its
own EDMX file and its own context.

==> but I can change the model and the xml of EDMX file at runtime right?!

You also mustn't use automatic database generation by code first
because any new module will either break your application or EF will
delete your current database.

==> thanks for this advice although I knew it before but ofcourse I will give more attention to it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

与他有关 2025-01-09 19:10:11

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

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

编辑:

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

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

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

如果您不希望模块中存在 EF 依赖关系,则要么根本不使用 EF,要么定义您自己的中间映射层,该中间映射层将转换为应用程序中的特定映射 - 大量工作零附加值。

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

我必须在启动时反映每个模块 dll,这意味着要反映大量繁重的 dll,并且......还有其他想法吗?

您是否见过 Photoshop、Visual Studio 甚至 MS Office 应用程序在启动过程中的情况?当您看到闪屏时,您认为发生了什么?应用程序正在初始化 - 它正在加载并初始化其功能和插件。即使服务器应用程序也可能需要几分钟才能完全启动。您正在构建模块化应用程序(而不是复合应用程序),因此您必须为该要求付费。

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

听起来 EF 对于企业复合应用程序来说并不是一个好的解决方案,对吧?

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

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

我应该切换到模型优先吗?!!

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

您也不能首先通过代码使用自动数据库生成,因为任何新模块都会破坏您的应用程序,或者 EF 将删除您当前的数据库。

上次编辑,因为这不是讨论论坛:

EF 不是我唯一的 DataProvider!我必须有其他一些 DP,例如...

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

请问有可靠的参考吗?!为什么我应该为每个添加一个存储库
模块万一只有一个存储库可以满足我的所有要求?
哪个是多余的?

参考就是经验。关于存储库和 EF 的问题有数百个。如果您想充分利用 EF,通用存储库将不允许这样做,否则它将必须公开其他提供者的实现中不可用的功能。如果您仅使用存储库来公开单个实体的 CRUD,那么您只是包装了 IDbSet 已经提供的内容。我知道您正在使用存储库来隐藏您的提供商地狱。

事实上,我正在尝试定义自己的映射层,因为我的应用程序架构中需要它。它对我来说并非毫无用处。

您将为每个提供者特定的映射编写一些自定义映射(可能是 XML)和转换器。我不确定您期望什么更好的答案 - 除了这不是一个好方法。

如果 EF 支持(据我所知不能),则将在每个模块加载和映射实体中工作的模型或中间映射器层我需要每个提供程序的引导程序之类的东西来映射实体

它不会缺少 EF 的一部分。它根本超出了 EF 的范围。 EF 定义的任何中间层仍将是 EF 的一部分,并且不受其他工具支持。 EF 可以在创建模型时加载实体,但要加载它们,您必须告诉 EF 它们的存在以及如何映射它们 - 这就是我最初的答案所解释的。

我不会就我的应用程序及其架构进行演讲,但我认为仅此而已就足以让您知道这是一个复合/模块化应用程序

它可以,但复合部分没有这些挑战,因为复合的每个组件应用程序独立于其余部分,并且可以使用完全不同的持久性。您面临的挑战是每个模块化组件的内部挑战。

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

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

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

You can make a requirement that each module must contain mapping classes for every new entity it uses. When you start the application you will just use reflection to get all classes derived from StructuralTypeConfiguration<> (includes both entities and complex types), create instances of these types and add them to Configurations collection in DbModelBuilder (can be done in OnModelCreating).

It will take some time but it will happens only once when context is used for the first time. You can trigger this creation during application start - applications simply need some time to start and configure all infrastructure they need to use.

Edit:

I have to reference EntityFramework.dll in every module which is not suitable in this case.

Yes. You want to allow other developers to define their own entities which will be persisted by your core application. In such case they must use your persistence framework of choice to tell your application how to persist their entities.

If you use repositories each module should even contain its own repositories for working with its own entities - generic repository doesn't exists. Generic repository is redundant useless layer which only makes work with ORM of your choice much harder. To make it clear - correct implementation of repository pattern is not generic. It is specific and it expose data access functionality for single entity or aggregate root.

If you don't want EF dependency in modules either don't use EF at all or define your own intermediate mapping layer which will be converted to specific mapping in your application - a lot of work with zero added value.

Other option is simply not allowing your modules to use new entities because it looks more like your current expectation. If module developer must define new database tables for his entities he must also be able to work with persistence and define mapping between tables and his entities.

I have to reflect each module dll at startup which means lots of heavy dll's to be reflected and ... is there any other Idea?

Have you ever seen applications like Photoshop, Visual Studio or even MS Office applications during their startup? What do you think is happening when you see splash screen? Application is initializing - it is loading and initializing its features and plugins. Even server application can need minutes to be fully started. You are building modular application (not composite) so you must pay for that requirement.

If you don't want to use reflection yourselves you can use MEF for building modularized infrastructure.

It sounds that EF is not a good solution for enterprise composite app right?

You didn't propose any enterprise requirement that shouldn't be fulfilled by EF. You just fight with your expectations to allow module developers to use new entities but don't give them ability to describe how these entities will be persisted - but who will describe it?

You are not building composite application. Composite application takes existing functionality (components, existing applications) which works separately and composethem to a new application. You are building modular application where your core can host another modules but those modules cannot run without your hosting infrastructure.

Should I switch to Model First?!!

Model first (and EDMX generally) is really not suitable for your expectations because in case of model first each module will need its own EDMX file and its own context.

You also mustn't use automatic database generation by code first because any new module will either break your application or EF will delete your current database.

Last Edit because this is not discussion forum:

EF is not my only DataProvider! I have to have some other DP such as ...

I don't know why you do that but it is wrong. Single application (even modular) should use single provider (ORM mapper). If you have other data providers because of some legacy code so be it but you should establish single provider policy for all new code. Otherwise you are fighting with your over architectured application not with EF. In such case your modules will always use only single dependency on provider.

May I ask for any reliable ref?! Why should I add one repository per
module in case only one repository can do all of my requirements?
which is redundant?

Ref is experience. There are hundreds of questions about repository and EF. If you want to use full advantage of EF, generic repository will not allow it or it will have to expose features which are not available in implementations for other providers. If you use repository just to expose CRUD for single entity you are just wrapping what IDbSet already provides. I understand that you are using repositories to hide your providers hell.

In fact I'm trying to define my own mapping layer because I need it in my app architecture.it is not useless for me.

You are going to write some custom mapping (probably XML) and convertor for each provider specific mapping. I'm not sure what better answer do you expect - except that it is not a good way to go.

A model or a intermediate mapper layer which will work in each module load and map the entities if the EF support (which can't as I know) I need something like bootstrapper for each provider to map the entities

It is not missing part of EF. It is simply out of scope of EF. Any intermediate layer defined by EF will still be part of EF and not supported by other tools. EF can load entities when it creates model but to load them you must tell EF about their existence and how to map them - that was what my initial answer explained.

I'm not going to give lecture about my app and it's architecture but I think just this much is enough that you know this is a composite/modular application

It can be, but composite part don't have these challenges because each component of composite application is independent on the rest and can use completely different persistence. The challenge you are facing is internal to every single modular component.

But I can change the model and the xml of EDMX file at runtime right?

Try it. Hint: there is no public API to operate with this XML on low level basis and there is no public API to modify loaded model. It is possible to change EDMX before you load it but it generally means writing custom parser and xml builder for SSDL, MSL and CSDL. You will have one set of mapping files updated by all installed modules. You will also have to code reverse operation to uninstall the module and correctly remove all features from mapping. Any bug can broke whole your application because mapping will be corrupted. My initial idea with loaded configurations for code mapping will take you less than one day. How long will it take to build this?

If you want to go this way remove EF from your project completely and start using NHibernate and hbm mapping files. Module developer will create assembly with module logic and new entities, script for database tables and hbm file for each entity. Module installation will create table, add assembly to module location and add hbm files to mapping pick up directory. Your NHibernate session will load all mapping files from that directory.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文