【问题标题】:Entity Framework circular dll reference实体框架循环 dll 参考
【发布时间】:2017-02-18 22:19:51
【问题描述】:

我在当前(悲伤)状态下的解决方案:

我希望我的业务层数据提供者不可知(这不是一件好事吗?),只需要一个接口,这样我就可以将 EF 与 NHibernate 或 Linq 切换到 Xml 或我或我的老板想要的任何类型的持久性提供者使用(或在这个项目完成后 2 秒内不可避免地发明的新的上级)。

IPersistenceProvider 是那个接口,我可以用 Unity 注入它(不是游戏平台,DI 容器)。对我来说,IPersistenceProvider 属于数据层,我们可以继续添加文件夹(如 EntityFramework),因为需要将新的持久性范例添加到我的简历(或项目)中。

因此,我的业务 dll 依赖于我的数据 dll。下面是业务 dll 中的一些代码,具体取决于数据 dll:

using System;
using Atlas.Data.Kernel;

namespace Atlas.Business.Kernel
{
  public abstract class BusinessObject
  {
    public BusinessObject(IPersistenceProvider p)
    {

    }


    public Guid Id;

  }
}

我也觉得我的DatabaseContext 属于数据层。但是 EF 让您引用其 DbSets 的具体类型,这意味着 AtlasDataKernel dll 需要依赖于 AtlasBusinessKernel dll,这将使循环 dll 引用。 En plus(这也是法语),一个指向业务层具体类型的数据层东西对我来说很陌生。 DatabaseContext 想要在业务 dll 中上线,但这是将我的业务层与特定的持久性策略工件耦合。

如何解决这个问题?我可以将它折叠到一个 dll 中(事实上,我在以前的项目中也这样做过),但这有点糟糕,我将无法进入 .Net Architects 俱乐部。他们会嘲笑我的“1 N 太少”架构,并嘲笑我离开会议。 WWDED? (Dino Esposito 会做什么?

【问题讨论】:

  • IPersistenceProvider 的用途是什么?
  • @SergeyBerezovskiy,它是 Bridge OO 模式中的 Bridge 接口/抽象。具体的持久性提供者(例如,EFPersistenceProvider)将实现它。
  • 您的逻辑(需要循环依赖)似乎有缺陷 - 或者您的模式选择可能不适合这项工作。 IE。我根本不明白为什么您需要依赖业务层。不清楚,也许您应该制作一个带有具体类的小项目来展示它。任何数据提供者(接口)都应该只为接口或 POCO 等提供通用方式。
  • @NSGaga,EF 需要具体引用业务类型来设置“模型”(DbContext),例如:public virtual DbSet<Category> Categories { get; set; }

标签: c# entity-framework circular-reference


【解决方案1】:

从实现中拆分声明。

EntityFramework 子目录应该是一个单独的程序集(例如 AtlasDataKernelEF),其中包含 EF 内容和IPersistenceProvider 的实现,从而解决循环引用。

此外,如果您真的需要使用不同的 ORM,您可以让您的生产可执行文件摆脱所有 EF 库。

您不会概述如何实例化 EF 数据访问,但您肯定需要将其包装在某种工厂类中。

【讨论】:

  • 澄清一下,AtlasDataKernelDataEF 将取决于AtlasKernalBusinessAtlasKernalDataAtlasKernalDataAtlasKernalBusiness 没有引用 EntityFramework,只有 AtlasDataKernelDataEF 有。而且,AtlasDataKernelDataEF.PersistenceProvider 将通过 DI 实例化并成功地提供给 BusinessObject,即使没有 dll 引用它(b/c DI 就是这样工作的)
【解决方案2】:

您的项目 AtlasBusinessKernel 不应引用 AtalsDataKernal 类中的任何资源。 AtalsBusinessKernel 需要使用的 AtalsDataKernal 中的任何资源都应表示为 AtalasBusinessKernal 项目中的接口,可以是 IDataConext 接口或存储库接口。

这仅在您有第三个项目实际使用 AtalsBusinessKernal 项目时才有效,可能是代表 UI 的 Web 应用程序或控制台应用程序。该项目将负责实例化 DatabaseContext,最好使用 DI。

// In your AtlasDataKernal
public class DatabaseContext : IDataContext
{
      // implementation
}

// In your AtlasBusinessKernal
public class MyBusinessLogic
{
     private IDataContext dataContext;
     public MyBusinessLogic(IDataContext context)
     {
        this.dataContext = context;
     }
}
// In your web application or whatever project type it might be
public class MyWebApp
{
      public DoSomeThing()
      {
          IDataContext context = new DatabaseContext();
          MyBusinessLogic logic = new MyBusinessLogic(context);
      }
}

【讨论】:

  • 你所拥有的就是我最终所做的。 IDatabaseContextIPersistenceProvider<T>MyBusinessLogicDatabaseObject 这是我所有业务对象的基础。然而,IPersistenceProvider<T>DatabaseObject 生活在数据中,但我猜他们可以生活在商业中。在我看来,它们只是数据-y。
  • 欢迎来到 S/O。 +1
猜你喜欢
  • 1970-01-01
  • 2011-10-22
  • 2016-10-21
  • 1970-01-01
  • 1970-01-01
  • 2019-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多