【问题标题】:EF N-Tier Architecture [closed]EF N 层架构 [关闭]
【发布时间】:2015-04-04 23:02:14
【问题描述】:

简介

我们需要构建一个 n 层应用程序,因为我们希望在多个平台上共享我们的 BL,并且只编写一次 DAL。我已经对这个主题进行了一些研究。

可以在 Davide Piras 的帖子中阅读:MVC3 and Entity Framework 每个 VS 解决方案必须至少有 4 层。到目前为止一切顺利。

他还表示,DAL 项目是唯一允许知道正在使用 EF 的项目。

问题 1:

我假设“接口”项目的接口是我的 EF 实体的 1 对 1 表示,我对此是否正确?还有,这些接口应该被用作不同层之间的类型吗?

问题 2:

MSDN 建议 DbContext 的生命周期应该是每个 WebApp 请求一个上下文,并且在 WPF 或 WinForms 项目中每个表单一个上下文。那么,如何在不向我的 GUI 层添加“System.Data.Entity”的情况下实现这一点?

提前谢谢!

【问题讨论】:

  • 谢谢反对,如果我遗漏了什么,请发表评论。我已经投入了一些精力和时间来问这些问题。

标签: c# entity-framework architecture n-tier-architecture


【解决方案1】:

您需要将Unit of WorkRepository 模式与StructureMapUnity 等依赖注入框架一起使用。

基本上,你需要做的就是创建接口:

public interface IUnitOfWork
{
    void SaveChanges();
}

public interface IRepository<TItem>
{
    TItem GetByKey<TKey>();

    IQueryable<TItem> Query();
}

现在,在您的 DbContext 类中实现上面的接口,并在您的业务层的某处注册接口的实现:

public void RegisterDependencies(Container container)
{
    // Container is a Structure Map container.
    container.ForRequestedType<IUnitOfWork>()
        .CacheBy(InstanceScope.HttpContext)
        .TheDefaultConcreteType<DbContext>();    
}

请参阅StructureMap Scoping Docs,了解如何配置实例的范围。

现在,有了所有这些代码,需要执行一些数据操作的每个 Business Layer 类将如下所示:

public class SomeService
{
    public SomeService(IRepository<SomeItem> repository, IUnitOfWork unitOfWork)
    {
        this.repository = repository;
        this.unitOfWork = unitOfWork;
    }

    public void MarkItemCompleted(int itemId)
    {
        var item = repository.GetByKey(itemId);
        if(item != null)
        {
            item.Completed = true;
            unitOfWork.SaveChanges();
        }
    }
}

现在,将服务的创建隐藏在工厂后面:

public class ServiceFactory
{
    private readonly Container container;// = initialize the container

    public TService CreateService<TService>()
    {
        return container.GetInstance<TService>();
    }
}

并且在您的 GUI 层中,仅调用通过 ServiceFactory 创建的服务类的方法;如果您的 GUI 是 ASP.NET MVC 项目,则不需要创建 ServiceFactory 类 - 您可以从 DefaultControllerFactory 派生并覆盖 GetControllerInstance 方法。示例见the answer here

【讨论】:

  • 感谢您的明确回复!这是非常有帮助的。我已经遇到过存储库和 UOW 模式。我认为回购的实施应该在 DAL 中,我正确吗?再次感谢。
  • @MarkRijsmus,是的,它应该在数据访问中。
【解决方案2】:

首先不要!!!在多个平台上共享您的 DAL。分享您使用 DAL 的 BL。只要您的 BL 代表您的应用程序要求的解决方案,您就不需要公开您的 DAL,请不要公开。此外,暴露 DAL 的缺点是向黑客暴露了更多漏洞,并且直接访问 DAL 为您的 BL 中的业务逻辑、控制和验证提供了 btpass 机制。

答案 1: 可能但不是必须的。考虑到 SOA,我建议使用 DTO。它们要么是实体,要么是多个和/或部分实体的更复杂的复合类。如果您使用实体,这使您可以更灵活地通过 BL 提供信息(您可以通过一个方法调用一次发送多个数据部分)并隐藏第三方用户的实体(也是 DB 结构),从而提供更好的安全感。

答案 2: 同样,考虑到 SOA,不要根据您的用户界面构造您的 BL/Service 方法。 BL(顾名思义)根据“工作如何完成”而不是“用户如何在屏幕上完成工作”提供数据。如果您尝试从 GUI 管理您的数据,您也将开始违反 N 层架构。 不要!!!在 DAL 之外使用任何数据特定的类和/或方法。这将是分层的真正用途。

问候。

【讨论】:

  • 感谢您的快速响应!对不起,我的意思不是共享 DAL,而是将它暴露给其他 GUI,而只写一次!我的错。
  • 我很高兴能帮上忙。
  • 是的,你帮了大忙;)。我会在几个小时内标记为答案,我仍在等待更多意见,我认为当问题仍未得到解答时,人们会更加渴望。
  • 没问题。我回答是为了帮助,而不是为了声誉。祝你有美好的一天。
  • 是的,必须在BL中完成。任何 UI 都只会看到您的 BL(作为 API),并且只会与该层进行通信。如何转换数据取决于您使用的语言和/您的开发偏好。在我当前的项目中,我们仅使用 ADO.NET,因此我通过存储过程从数据库中获取数据并从 DAL 返回接口。在 BL 中,我从接口创建模型(我的 UI 仅是 ASP.NET MVC !!!)并返回它。但我更喜欢使用 ORM 工具(例如 DAL 的实体框架)并编写 LinQ 查询来获取 [this] (tinypic.com/r/2qnd3y1/8) 结构。
猜你喜欢
  • 2010-11-14
  • 1970-01-01
  • 2012-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-27
相关资源
最近更新 更多