重构:从自定义数据访问层切换到实体框架

发布于 2024-12-06 06:16:52 字数 603 浏览 0 评论 0原文

我是一名 .NET 开发人员,作为重构项目的一部分,我有几个问题。

我们的软件当前使用 Active Record 模式(数据对象和业务对象之间的一对一映射)。不好的是业务对象继承自数据对象,导致层之间的高度耦合。

我们的目标是从自定义数据访问层(基于 ADO.NET)切换到实体框架。我们面临的限制是不要破坏代码,以便我们的旧应用程序仍将使用旧的数据访问层进行编译和运行,同时允许我们在新项目中使用 EF。

我这样做的第一个想法是打破继承并将数据对象作为业务对象的属性(并使用接口或抽象类来注入数据对象,无论是我们的自定义层还是实体框架)。属性将从数据对象迁移到业务对象,业务对象将充当某种“代理”来访问数据对象的属性。

这是一个可行的解决方案吗?那仍然会使用活动记录模式(我不太喜欢这个,因为我们的业务层已经变得相当大)所以如果您有任何其他想法,请不要犹豫。

我的另一个问题是关于实体框架的生成。我们需要实体属性与旧数据对象具有相同的名称(我们将使用抽象类以便允许业务对象调用数据对象的属性,无论是我们的自定义数据对象还是 EF 实体) 。实现这一目标的最佳方法是什么?使用 T4 生成实体还是采用 EF 代码优先方法?

我对任何建议都非常开放,所以请毫不犹豫地提出其他方法。感谢您抽出时间。

I am a .NET Developer and as part of a refactoring project, I have a few questions.

Our software is currently using an Active Record pattern (one to one mapping between the data objects and the business objects). The bad thing is that the business objects inherits from the data objects, inducing highly couple between the layers.

Our goal is to switch from our custom data access layer (based on ADO.NET) to Entity Framework. The constraint we have is not to break the code so that our older applications will still compile and run using the old data access layer while allowing us to use EF for the new projects.

My first idea to do so is to break the inheritance and have the data object as an attribute of the business object (and use an interface or abstract class in order to inject the data object, whether it is our custom layer or Entity Framework). The properties would be migrated from the Data objects to the business objects which would act like some kind of "proxy" to access the properties of the data objects.

Would that be a viable solution ? That would still use the active record pattern (and I don't like this a lot, since our business layer has become quite large) so if you have any other idea, please don't hesitate.

My other question is about the Entity framework generation. We need the entities properties to have the same name as the old data objects (we would use an abstract class in order to allow the business objects to call the properties of the data object, whether it is our custom data object or the EF entities). What would be the best way to accomplish that ? Using T4 to generate the entities or have an EF Code first approach ?

I am very open to any suggestion, so please do not hesitate to propose other approaches. Thanks for your time.

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

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

发布评论

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

评论(1

屌丝范 2024-12-13 06:16:52

这是一个可行的解决方案吗?如果您要使用实体框架启动一个新项目,我会说:不。因为实体框架是存储库的实现工作单元模式和活动记录模式是一种完全不同的方法。

即使您将非 POCO、EntityObject 派生实体与实体框架一起使用,这些实体也不会成为真正的活动记录,因为 EntityObjectEntityCollection 的持久性功能code> 暴露是有限的(我相信是设计使然)。 EntityObject 仅支持更改跟踪,EntityCollection 具有诸如 LoadCreateSourceQuery 之类的函数,支持对该特定集合的查询。但您手头没有完整的 ObjectContext 来发出任意查询、删除对象或保存更改。

EF 4.1 和 DbContext 甚至不再支持此功能,因为 DbContext 不允许使用 EntityObject 派生实体。这是一种纯粹的 POCO 方法,具有不感知实体的持久性。只有延迟加载和更改跟踪代理知道上下文,但这只是运行时的“透明”功能,您无法针对此代理上下文进行编程。

现在,您不再开始一个新项目,而是拥有一个必须在很大程度上尊重的架构。如果您的数据对象基类(实现 Active Record)具有诸如 LoadMeSaveMeLoadCustomersContacts 等方法,并且您在以下位置使用这些方法:您的业​​务/服务层,并且您不能或不想更改此层,那么您可能必须使用实体框架找到有效的 Active Record 方法。

这是一种非标准方法,有点违反实体框架的架构。它提出了一些问题,例如:如何管理与对象生命周期相关的上下文创建和生命周期?您如何处理事务性和非事务性行为? (SaveChanges 本身就是一个事务,您无法保存单个“行”或实体,您总是完全保存上下文/工作单元中的内容 - 修改、添加或删除。这可能不是行为您现在使用 ADO.NET 的 Active Record 方法已经具备了这一点。)

到底如何做到这一点?我不知道,我从来没有使用过这种方法。尝试在谷歌上搜索“实体框架和活动记录模式”或其他内容,也许您会发现一些内容并没有说“不要这样做!”。

对于您的另一个问题:我更喜欢使用 Code-First 的 DbContext ,以便于开发(这就是它的用途)。但请注意,有一些功能在 Code-First 中不受支持,需要基于 EDMX 的解决方案(我相信“模型定义的函数”就是其中之一)。此外,DbContext 尚不支持映射到存储过程。您可以通过上下文发出原始 SQL 语句,但这可以解决此限制。

这是我的观点。


顺便说一句:欢迎来到 Stackoverflow!你的问题对于这个网站的格式来说是有问题的,因为太笼统而且有点征求“意见”。我建议您将问题分解为更小的部分,并创建单独的更小、更具体的问题,也许用很少的代码片段来装饰,使其更加具体和有形。您通常会得到对此类问题的更多答复(并且比我上面的 blabla 更有价值的答复)。好消息是:您可以根据需要创建任意数量的问题。

Would that be a viable solution ? If you would start a new project with Entity Framework I would say: No. Because Entity Framework is an implementation of the Repository and Unit Of Work pattern and Active Record pattern is a quite different approach.

Even if you use Non-POCO, EntityObject derived entities with Entity Framework the entities don't become really active records because the persistence features which EntityObject or EntityCollection expose are limited (by design, I believe). EntityObject just supports change tracking and EntityCollection has functions like Load or CreateSourceQuery which support queries on that specific collection. But you don't have the full ObjectContext at hand to issue arbitrary queries, delete objects or save changes.

EF 4.1 and DbContext even don't support this anymore since EntityObject derived entities are not allowed with DbContext. It's a pure POCO approach with persistence unaware entities. There are only lazy loading and change tracking proxies which know the context, but that is only a "transparent" feature at runtime and you cannot program against this proxy context.

Now, you don't start with a new project but have an architecture you must respect in large parts. If your data object base classes (which implement Active Record) have methods like LoadMe, SaveMe, LoadCustomersContacts, etc. and you use these methods in your business/service layers and you cannot or don't want to change this layer, then you probably have to find a working Active Record approach with Entity Framework.

This is a non-standard approach and a bit against the architecture of Entity Framework. It raises questions, for example: How do you manage context creation and lifetime in relation to object lifetime? How do you handle transactional and non-transactional behaviour? (SaveChanges is a transaction by itself and you cannot save single "rows" or entities, you always save completely what's in the context/unit of work - modified, added or deleted. This is probably not the behaviour that your Active Record methods with ADO.NET have today.)

How to do that exactly? I don't know, I've never used this approach. Try to google for "Entity Framework and Active Record pattern" or something and perhaps you find a bit which doesn't say "Don't do that!".

To your other question: I'd prefer DbContext with Code-First for the ease of development (that's what it was made for). But be aware that there are a few features which are not supported in Code-First and require an EDMX based solution ("Model-defined functions" is one of them, I believe, among others). Also mapping to Stored Procedures is not yet supported in DbContext. You can issue raw SQL statements through the context though which can be a workaround for this limitation.

That's my view.


BTW: Welcome to Stackoverflow! Your question is problematic for the format of this site because too general and a bit asking for "opinions". I would recommend you to split your problem down into smaller parts and create separate smaller and more specific questions, perhaps decorated with little code snippets to make it more concrete and tangible. You usually get more response to such questions (and more valuable response than my blabla above). The good news is: You can create as many questions as you want.

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