Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 实体框架6.0与POCO的解耦实现_C#_.net_Entity Framework - Fatal编程技术网

C# 实体框架6.0与POCO的解耦实现

C# 实体框架6.0与POCO的解耦实现,c#,.net,entity-framework,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; } }

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

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会导致错误:

属性“Driver”不能配置为导航属性。 属性必须是有效的实体类型,并且该属性应具有 非抽象的getter和setter。对于集合属性,类型为 必须实现ICollection,其中T是有效的实体类型

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

  • 将我的POCO接口与实体进行硬耦合,这对可测试性和可移植性造成了影响
  • 在我的POCO和实体对象(bleh)之间添加过渡层
  • 抛开实体,用一些讨厌的Linq2SQL实现来解决这个问题,这些实现在某种程度上支持实体(尽管Linq2SQL抱怨EntityRefs,但它在EntitySet和接口上运行良好!)
  • 找到另一个ORM,它将允许我从实现数据提供程序中正确抽象POCO

或者我在这里遗漏了什么?

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

我已经做过几次了。如果您希望您的类完全独立,不受实体框架的任何特定影响,那么您必须进行一些小的更改。以下是我所做的:

  • 创建类来表示域实体。我在一个完全独立的程序集中完成了这项工作(出于各种原因),但您不必这样做
  • 使用中的类引用名称空间,并像往常一样将它们的集合添加到
    DbContext
  • 使用实体框架的Fluent配置API进行和
最后一部分意味着您可能无法使用像
[ForeignKey]
这样的属性,因为它们中的许多都存在于
System.Data.Entity
中,此时您正在使用实体框架的东西,所以您不妨接受耦合


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

您没有将POCO耦合到EF,另一种方法是完全合法的,因为域对象是应用程序的基本构建块。类似于整数、字符串等。。。 你不会用“接口”int吧?在任何时候,你扔掉EF和NH,例如,这将不会影响你的POCO在所有

现在,另一方面,您需要为自定义DbContext和业务类创建接口。通过这种方式,您可以出于测试目的模拟它们并更改实现

还有一件事——不要把EF从业务层抽象到自己编写的数据访问层。尽管这是可以实现的,但它也对您的业务层实现施加了大量限制。你必须发明自我折磨的技术来编写查询,否则会占用你5秒钟的时间

在我看来,理想的依赖关系图,是我经过大量实验后得出的,现在 看起来像这样

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


请注意,这里的业务层依赖于EF,如果我决定从EF(高度怀疑),我将不得不移植我的业务类。我认为,这是一个不太可能发生的事件,对于EF在我的商务课程中给我带来的所有舒适感来说,这是一个很小的代价。

我理解你的要求,但我不理解这一点:“我的数据层与实体的硬耦合”。实体框架是一个数据层。您可能是指将域与数据层耦合。此外,我认为任何ORM都会导致硬耦合,测试它们的唯一方法是通过集成测试。。。更新了问题。我想最大的问题是我正在连接我的POCO,如果我根本不需要属性我的POCO,我几乎什么都得不到。。。然而,我在EntityTypeConfiguration的实现中遇到了一个问题,不允许我进行1对1的关系,到目前为止,我实现这一点的唯一方法是使用ForeignKey属性,这就是为什么我再次尝试在POCO中使用接口的原因。此外,我一直是这样学习的,因为这是从Linq2SQL抽象POCO的唯一方法。好吧,我想我解决了EntityTypeConfiguration问题,我将继续努力,从我的POCO中删除接口,然后继续,看看它是如何进行的,谢谢!在我的项目中,我保留了edmx模型,禁用了模型生成TT文件,并引用了我的域对象程序集。这样pocos就没有任何属性,我不需要进行流畅的映射,而且我仍然可以使用模型设计器。我还修改了上下文TT文件以包含域名称空间,这样它就可以看到pocos。这是正确的,但仍然存在耦合,因为EF要发挥最佳功能,“域”类应该满足几个设计准则。我认为,类模型与存储模型之间不会有太大的差异。尽管这些设计准则在许多其他ORM中仍然适用,而且通常不会有太多的情况下,您的存储模型和域模型会有根本性的不同。不过,就“耦合”而言,我说的是严格意义上的耦合