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

时间:2014-04-20 07:40:48

标签: c# .net entity-framework

假设我有几个基本对象和接口:

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; }
}

如果我使用" Driver"的实现类。而不是" IDriver"一切都很开心(所以我们忽略了我缺少所有其他值的附加配置),但是使用IDriver最终会出现错误:

  

物业'司机'无法配置为导航属性。   该属性必须是有效的实体类型,属性应该具有   一个非抽象的getter和setter。对于集合属性的类型   必须实现ICollection,其中T是有效的实体类型。

据我所知,实体实际上并没有以任何方式支持这一点,我的选择是:

  • 将我的POCO接口硬连接到实体,给可测试性和可移植性带来麻烦,欢迎使用。
  • 在我的POCO和实体对象(bleh)之间添加过渡层。
  • 抛出实体,用一些讨厌的Linq2SQL实现来解决这个问题(虽然Linq2SQL抱怨EntityRefs,它可以和EntitySets和接口一起运行!)。
  • 找到另一个ORM,它允许我从我的实施数据提供者中正确地抽象我的POCO。

我在这里遗漏了什么?

3 个答案:

答案 0 :(得分:2)

我已经做了几次。如果您希望您的课程完全独立,没有任何特定于实体框架的内容,那么您必须进行一些小的更改。这就是我的所作所为:

  • 创建表示域实体的类​​。我是在一个完全独立的装配中完成的(出于各种原因),但你不必这样做。
  • 在您的课程中引用名称空间,然后照常将DbContext添加到[ForeignKey]
  • 将实体框架的Fluent配置API用于map your typestheir relationships

最后一部分意味着您可能无法使用System.Data.Entity之类的属性,因为其中许多属于[{1}},并且此时您正在使用实体框架内容,因此您可能会像好吧,接受耦合。

这确实意味着您需要做更多的工作来建立关系,但这并不是太糟糕,当您完成后,您的域类与实体完全分开框架,允许您模拟它进行测试,或者非常轻松地将其交换为另一个ORM。

答案 1 :(得分:2)

您没有将POCO与EF相关联,它是相反的,完全合法,因为域对象是您的应用程序的基本构建块。类似于整数,字符串等...... 你不会"界面" int,好吗?例如,在任何时候你扔EF并取NH,这根本不会影响你的POCO。

现在,另一方面,自定义DbContext和业务类是创建接口所需的东西。通过这种方式,您可以模拟它们以进行测试并更改实现。

还有一件事 - 不要让自己陷入在自编写数据访问层中从业务层中抽象EF的想法。虽然这是可以实现的,但它也会对您的业务层实施施加大量限制。你必须发明自我折磨技术来编写查询,否则你需要5秒的时间。

在我看来,理想的依赖关系图,我在经过大量实验后想出来了 看起来像这个enter image description here

域对象,业务和上下文接口是应用程序的核心。其他层彼此独立,因此是可测试的。

请注意,这里的业务层依赖于EF,如果我决定从EF切换(高度怀疑它),我将不得不移植我的业务类。我相信,这是一个非常不可能发生的事件,并且在我的商务课程中为我提供的所有舒适度都要付出很小的代价。

答案 2 :(得分:1)

你不想为你的实体创建接口,因为你最终会得到你在这里的头接口,因此接口根本不是抽象,没有什么价值。如果您创建角色接口,那么您可以轻松地在测试中删除实现以返回您希望的实体。