[英]Entity Framework 6.0 Decoupling Implementing From POCOs
假设我有几个基本对象和接口:
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是有效的实体类型。
据我所知,实体实际上并没有以任何方式支持这一点,我的选择是:
或者我在这里遗漏了什么?
我做过几次这样的事。 如果您希望您的类完全独立,没有任何特定于Entity Framework的内容,那么您将不得不进行一些小的更改。 这是我做的:
DbContext
中。 最后一部分意味着你可能无法使用像[ForeignKey]
这样的属性,因为它们中的许多都存在于System.Data.Entity
中,此时你正在使用Entity Framework的东西,所以你不妨接受耦合。
这确实意味着你将不得不做更多的工作来建立关系,但它并不是太糟糕,当你完成后你的域类完全独立于实体框架,允许你模拟它进行测试或交换它非常无痛地用于另一个ORM。
您没有将POCO耦合到EF,它是另一种方式并且完全合法,因为域对象是应用程序的基本构建块。 类似于整数,字符串等...你不会“接口”int,不是吗? 例如,在任何时候你扔EF并取NH,这根本不会影响你的POCO。
现在,另一方面,自定义DbContext和业务类是创建接口所需的东西。 这样,您可以模拟它们以用于测试目的并更改实现。
还有一件事 - 不要让自己陷入在自编写数据访问层中从业务层中抽象EF的想法。 虽然这是可以实现的,但它也会对您的业务层实施施加大量限制。 你必须发明自我折磨技术来编写查询,否则你需要5秒的时间。
在我看来,理想的依赖图,经过大量的实验我想出来了,现在看起来像这样
域对象,业务和上下文接口是应用程序的核心。 其他层彼此独立,因此是可测试的。
请注意,这里的业务层依赖于EF,如果我决定从EF切换(高度怀疑它),我将不得不移植我的业务类。 我相信,这是一个非常不可能发生的事件,并且为我在商务课程中提供的所有舒适性付出的代价很小。
您不希望为实体创建接口,因为您最终会得到头部接口,因此接口根本不是抽象,并且没有什么价值。 如果您创建角色接口,那么您可以轻松地在测试中删除实现以返回您希望的实体。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.