简体   繁体   English

实体框架6.0实现与POCO的实现

[英]Entity Framework 6.0 Decoupling Implementing From POCOs

Lets say I have a couple basic objects and interfaces for them: 假设我有几个基本对象和接口:

interface ICar
{
  int Id { get; set; }

  int DriverId { get; set; }

  IDriver Driver { get; set; }
}

class Car: ICar
{
  int Id { get; set; }

  [ForeignKey("Driver")]
  int DriverId { get; set; }

  IDriver Driver { get; set; }
}

If I use the implementing class of "Driver" instead of "IDriver" everything is happy (so lets ignore I'm missing additional configuration for all the other values), however using IDriver ends up with the error: 如果我使用“Driver”的实现类而不是“IDriver”,一切都很高兴(所以我们忽略了我缺少所有其他值的附加配置),但是使用IDriver最终会出现错误:

The property 'Driver' cannot be configured as a navigation property. 属性“Driver”无法配置为导航属性。 The property must be a valid entity type and the property should have a non-abstract getter and setter. 该属性必须是有效的实体类型,并且该属性应具有非抽象的getter和setter。 For collection properties the type must implement ICollection where T is a valid entity type. 对于集合属性,类型必须实现ICollection,其中T是有效的实体类型。

So far as I understand it entity doesn't actually support this in any way, my options are: 据我所知,实体实际上并没有以任何方式支持这一点,我的选择是:

  • Hard couple my POCO interfaces to entity, throwing a wrench into testability and portability, welp. 很难将我的POCO接口连接到实体,为可测试性和可移植性带来了麻烦。
  • Add a transition layer between my POCOs and entity objects (bleh). 在我的POCO和实体对象(bleh)之间添加过渡层。
  • Throw entity out, sort of work around this with some nasty Linq2SQL implementations that sort of support this (though Linq2SQL complains about EntityRefs, it plays fine with EntitySets and interfaces!). 抛出实体,用一些讨厌的Linq2SQL实现来解决这个问题(虽然Linq2SQL抱怨EntityRefs,它可以与EntitySets和接口一起运行!)。
  • Find another ORM that will allow me to properly abstract my POCOs from my implementing data provider. 找到另一个ORM,它允许我从我的实施数据提供者中正确地抽象我的POCO。

Or am I missing something here? 或者我在这里遗漏了什么?

I've done this a few times. 我做过几次这样的事。 If you want your classes to be entirely separate, free from anything specific to Entity Framework, then you'll have to make a few small changes. 如果您希望您的类完全独立,没有任何特定于Entity Framework的内容,那么您将不得不进行一些小的更改。 Here's what I did: 这是我做的:

  • Create classes to represent domain entities. 创建表示域实体的类​​。 I did this in a completely separate assembly (for various reasons) but you don't have to. 我是在完全独立的装配中完成此操作(出于各种原因),但您不必这样做。
  • Reference the namespace(s) with your classes in and add sets for them to the DbContext as normal. 引用带有类的命名空间,并将它们的集合添加到DbContext中。
  • Use Entity Framework's Fluent Configuration API to map your types and their relationships . 使用Entity Framework的Fluent Configuration API来映射您的类型 及其关系

That last part means you may not be able to use attributes like [ForeignKey] , as many of them live in System.Data.Entity and at that point you're using Entity Framework stuff so you might as well just accept the coupling. 最后一部分意味着你可能无法使用像[ForeignKey]这样的属性,因为它们中的许多都存在于System.Data.Entity中,此时你正在使用Entity Framework的东西,所以你不妨接受耦合。

This does mean you'll have to do a little more work to set up the relationships, but it's not too bad, and when you're done your domain classes are entirely separate from Entity Framework, allowing you to mock it for testing or swap it for another ORM pretty painlessly. 这确实意味着你将不得不做更多的工作来建立关系,但它并不是太糟糕,当你完成后你的域类完全独立于实体框架,允许你模拟它进行测试或交换它非常无痛地用于另一个ORM。

You are not coupling POCOs to EF, it's the other way around and totally legitimate since domain objects are basic building blocks of your application. 您没有将POCO耦合到EF,它是另一种方式并且完全合法,因为域对象是应用程序的基本构建块。 Similar to ints, strings, etc... You would not "interface" int, would you? 类似于整数,字符串等...你不会“接口”int,不是吗? At any time you throw EF away and take NH, for example, this would not affect your POCOs at all. 例如,在任何时候你扔EF并取NH,这根本不会影响你的POCO。

Now, custom DbContext and business classes on the other hand ARE the things you need to create interfaces for. 现在,另一方面,自定义DbContext和业务类是创建接口所需的东西。 This way you can mock them for test purposes and change implementations. 这样,您可以模拟它们以用于测试目的并更改实现。

And one more thing - do not trap yourself with the idea of abstracting EF from the business layer in a self written data access layer. 还有一件事 - 不要让自己陷入在自编写数据访问层中从业务层中抽象EF的想法。 Although, this is achievable, it also puts tons of restrictions on your business layer implementations. 虽然这是可以实现的,但它也会对您的业务层实施施加大量限制。 You'll have to invent self torturing techniques to write queries which would take 5 seconds of your time otherwise. 你必须发明自我折磨技术来编写查询,否则你需要5秒的时间。

In my opinion, the ideal dependency diagram, I came up with after a lot of experiments, now looks like this 在我看来,理想的依赖图,经过大量的实验我想出来了,现在看起来像这样 在此输入图像描述

Domain objects, business and context interfaces are the core of the app. 域对象,业务和上下文接口是应用程序的核心。 Other layers are independent of each other and therefore testable. 其他层彼此独立,因此是可测试的。

Be mindful thought, that business layer here is dependent on EF and if I ever decide to switch from EF (highly doubt it) I will have to port my business classes. 请注意,这里的业务层依赖于EF,如果我决定从EF切换(高度怀疑它),我将不得不移植我的业务类。 This, I believe, is a very unlikely event and a small price to pay for all the comfort EF gives me in my business classes. 我相信,这是一个非常不可能发生的事件,并且为我在商务课程中提供的所有舒适性付出的代价很小。

You don't want to create interfaces for your entities, as you'll end up with header interfaces as you have here, and therefore the interfaces are not abstractions at all and have little value. 您不希望为实体创建接口,因为您最终会得到头部接口,因此接口根本不是抽象,并且没有什么价值。 If you create role interfaces then you can easily stub out the implementations in tests to return the entities you wish. 如果您创建角色接口,那么您可以轻松地在测试中删除实现以返回您希望的实体。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM