【问题标题】:Appropriate layers of design abstraction for objects?对象的适当设计抽象层?
【发布时间】:2015-11-18 20:27:31
【问题描述】:

我最近重新开始了 ASP MVC 开发,对于 EF 6,我对设计逻辑有一些疑问。

我将采用以下模式: 控制器 -> 服务 -> 存储库 -> DbContext -> 数据库

我读过一些关于 UnitOfWork 模式的东西,但我总是做出类似的东西:

public abstract class BaseRepository : IDisposable
{
    SiteContext Context;
    public BaseRepository(SiteContext context) { 
        Context = context; 
        IsContextDisposable = false; 
    }

    public BaseRepository() { 
        Context = new SiteContext(); 
        IsContextDisposable = true; 
    }
}

public class ForumRepository : BaseRepository
{
}

因此,如果某个方法需要多个 repos,它可以只传递其单个 DbContext 并在以后处理它。

问题

  1. 我的存储库是否应该使用实体框架模型(用于构建我的代码优先数据库)?或者 repo 是否应该获取它们并立即使用 Automapper 或类似的东西将 EF 模型转换为域对象?

  2. 服务的意义何在?为什么我不能直接从控制器实例化存储库?服务的职责是什么?

  3. 将实体模型转换为领域对象然后再转换为视图模型是否正常?

【问题讨论】:

  • 从那时起以异步方式使用 DbContext,上层可能会认为 Repo 已完成并过早处置它 - 据我所知,这不可能发生。
  • 是的,我要编辑我的帖子,因为我已经阅读了大量关于 DbContext 如何不是线程安全的文章,而且启动另一个上下文显然不是什么大问题.
  • 异步和线程根本不是一回事。
  • 对不起,我指的不是 C# 异步模式,我指的是多线程。

标签: c# asp.net asp.net-mvc entity-framework entity-framework-6


【解决方案1】:

问题 2 的答案是松散耦合。如果您直接在控制器中使用存储库,这会产生紧密耦合,并且如果您想更改数据访问权限,则必须更改控制器。如果您有服务层,则无需更改控制器。现在,如果您的存储库基于一个接口(我们称之为 IDAL),该接口定义了您可能需要的所有数据访问方法(例如 GetBooksByAuthor 等),您可以取消服务层并将存储库直接注入您的控制器。这样,如果您想更改数据访问,您可以从 IDAL 接口派生并将这个新的具体数据访问层注入您的控制器。

1 和 3 的答案取决于您的应用程序的复杂性。如果您的数据库表与您的域对象非常匹配,那么 repo 可以直接使用实体模型。如果没有,那么最好将它们转换为域对象并将它们传递给服务或控制器以进行进一步的业务逻辑。领域模型通常会在控制器中转换为 ViewModel,然后再发送到视图。

【讨论】:

  • 嘿苛刻,感谢您的洞察力。 OOC,根据您的经验,您更喜欢哪个,通过服务层,还是通过依赖注入的某种 IRepository 接口?
  • 我个人更喜欢带有 DI 的 IRepository 接口。这样做有几个优点: 1. 它使测试更容易。在您的单元测试中,您可以创建 IRepository 的模拟实现并将其传递给控制器​​。 2.如果你想支持多个数据库或者你想改变数据库,你可以简单地创建另一个IRepo的实现,并在需要时注入你想要的实现。使用服务层方法,控制器总是调用直接调用存储库的服务,仍然存在一些(间接)耦合。
  • 哦,好吧,这是否意味着您将业务逻辑放在控制器中?业务逻辑不应该和表现层分开吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多