在基于WCF的企业应用程序中使用哪种实体框架变体

时间:2011-06-19 16:18:06

标签: wcf entity-framework architecture enterprise

我们正在设计一个包含大约100个表和复杂业务逻辑的应用程序。 Windows窗体将在客户端使用,WCF服务在服务器上使用MSSQL。

自定义DTO用于客户端 - 服务器通信,业务实体不分发。

要使用的实体框架的哪个变体(及其原因):

  • EF 4.0 EntityObjects
  • EF 4.0 POCO
  • EF 4.1 DbContext
  • 其他东西

数据库优先方法是一项要求。

另外,是否值得实现Repository模式?这似乎有点多余,因为映射本身有一个抽象级别,而使用DTO则有另一个抽象级别。我现在倾向于为每个返回IQueryable的实体使用自动生成的可扩展存储库,只是为了放置常见查询,但仍允许直接从服务层查询实体模型。

2 个答案:

答案 0 :(得分:2)

POCO的主要优点是这些类可以 你的DTO,所以如果你已经有了你正在使用的自定义DTO,POCO似乎有点多余。但是,由于您未提及单元测试作为要求,因此还有一些其他优点可能对您有价值,也可能没有价值。如果您打算编写单元测试,那么POCO仍然是可行的方法。您可能不会注意到4.0 POCO和4.1之间存在很大差异,因为您不会使用代码优先功能(免责声明:我只使用了4.0 POCO,所以我对任何细微的差异都不是很熟悉在两者之间,但它们似乎或多或少相同 - 基本上我已经在4.0中使用POCO并且没有看到任何让我想要更新所有内容以使用4.1的内容。

此外,根据您是否计划对此图层进行单元测试,在使用Entity Framework时,实现存储库/工作单元单元仍然很有用。它用于抽象出数据访问逻辑(上下文),而不是实体本身,并允许您在单元测试中模拟上下文。我所做的是复制我的上下文的T4模板并使用它来创建界面,然后编辑上下文的T4模板并让它实现该界面并使用IObjectSet<T>而不是ObjectSet<T>。所以而不是:

public class MyEntitiesContext
{
    public ObjectSet<MyClass> MyEntities
    ...
}

我最终得到了:

public interface IMyEntitiesContext
{
    public IObjectSet<MyClass> MyEntities;
}

public class MyEntitiesContext : IMyEntitiesContext
{
    public IObjectSet<MyClass> MyEntities
    ...
}

所以我想这真的归结为你是否打算为这一层编写单元测试。如果你不会做任何需要模拟你的上下文进行测试的东西,那么最容易使用的东西可能是4.0 EntityObjects,因为你不打算在层之间传递你的实体,它需要的工作量最少。实行。如果您打算使用模拟,那么您可能希望使用POCO并实现存储库/工作单元。

答案 1 :(得分:2)

使用哪种变体?基本上,一旦你有自定义DTO,唯一的问题是你想控制实体代码(他们的基类)并使它们独立于EF吗?你想先使用代码吗?如果所有问题的答案都是肯定的,那么您可以使用EntityObjects。如果你想让实体持久性无知或使用自定义基类,你应该去POCO。如果您想先使用代码或使用新的DbContext API,则需要使用EF 4.1。一些相关主题:

设计服务层时还需要考虑更多事项。您应该了解在WCF中使用EF时必须处理的复杂问题。您的服务将向WinForms应用程序提供数据,它将以“分离模式”与它们一起使用。一旦用户完成了他想要做的所有更改,他就会将数据发布回服务。但问题出在这里 - 你必须告诉EF发生了什么变化。例如,如果允许用户更改订单及其所有订单商品(更改商品数量,添加新商品,删除部分商品)you must say EF exactly what has changed,添加的内容和删除的内容。当你使用单个实体时很容易,但是一旦你允许用户改变对象图(特别是多对多关系),那就非常困难了。最常见的解决方案是加载整个图形并将状态从传入的DTO合并到加载和附加的图形。其他解决方案是使用Self tracking entities而不是EntityObjects / POCOs + DTO。

在讨论存储库时,我会向您推荐this answer,其中提到许多其他答案,讨论存储库,它们可能的冗余以及在使用它们时可能出错以使您的代码可测试。通常,只有在真正需要图层时才应添加每一层 - 因为可以更好地分离关注点。