【问题标题】:IOC container trying to reference DbContextIOC 容器试图引用 DbContext
【发布时间】:2013-12-05 15:29:36
【问题描述】:

我现在正在编写一个程序,它使用 StructureMap 作为 IOC 容器。 我已经实现了几个接口 - IUnitOfWorkIDataAccessRepository,它们在运行时使用以下类解析(它们在他们自己的项目中 - CardGame.EntityFrameworkProvider)。

EntityFrameworkRepository.cs

public class EntityFrameworkRepository<T> : IDataAccessRepository<T>
    where T : class
{
    private DbContext _ctx;
    private DbSet<T> set;

    internal EntityFrameworkRepository(DbContext ctx)
    {
        _ctx = ctx;
        set = _ctx.Set<T>();
    }

    public IEnumerable<T> Elements
    {
        get { return set; }
    }

    public T Get(int id)
    {
        return set.Find(id);
    }

    public void Add(T t)
    {
        set.Add(t);
    }

    public void Update(T t)
    {
         set.Attach(t);
        _ctx.Entry<T>(t).State = EntityState.Modified;
    }

    public void Delete(T t)
    {
        if (_ctx.Entry<T>(t).State == EntityState.Detached)
            set.Attach(t);
        set.Remove(t);
    }
}

EntityFrameworkUnitofWork.cs

public class EntityFrameworkUnitOfWork : DbContext, IUnitOfWork
{
    /// <summary>
    /// Creates an EntityFrameworkUnitOfWork.
    /// </summary>
    /// <param name="connectionStringOrName"></param> 
    public EntityFrameworkUnitOfWork(string connectionStringOrName) : base(connectionStringOrName)
    {
        Database.SetInitializer<EntityFrameworkUnitOfWork>(new DropCreateDatabaseIfModelChanges<EntityFrameworkUnitOfWork>());

        Creatures = new EntityFrameworkRepository<Models.Cards.Creature>(this);
        MagicCards = new EntityFrameworkRepository<Models.Cards.Magic>(this);
        EffectDescriptors = new EntityFrameworkRepository<Models.Effects.EffectDescriptor>(this);
    }


    #region Repositories
    public IDataAccessRepository<Models.Cards.Creature> Creatures
    {
        get;
        private set;
    }

    public IDataAccessRepository<Models.Cards.Magic> MagicCards
    {
        get;
        private set;
    }

    public IDataAccessRepository<Models.Effects.EffectDescriptor> EffectDescriptors
    {
        get;
        private set;
    }
    #endregion

    public new void SaveChanges()
    {
        base.SaveChanges();
    }
}

最后,在我的主要方法中 - 在另一个项目中 - 我使用 StructureMap 将依赖项绑定在一起。 主要

        ObjectFactory.Configure(x =>
        {
            x.Scan(scan =>
            {
                scan.LookForRegistries();
                scan.Assembly("CardGame.DataAccess");
                scan.Assembly("CardGame.EntityFrameworkProvider");
            });

            #region Persistence
            x.For<CardGame.DataAccess.IUnitOfWork>().Use(new CardGame.EntityFrameworkProvider.EntityFrameworkUnitOfWork("MyConnectionString"));
            #endregion
        });

我的问题是,随着EntityFrameworkUnitOfWork 扩展DbContext,我的CardGame.Server(包含Main.cs 的项目)无法编译,因为它不(故意)包含对EntityFramework 的引用。我正在尝试使其尽可能与数据库无关,到目前为止一切顺利,但是当我创建 EntityFrameworkUnitOfWork 扩展 DbContext (所以我可以应用 DropCreateDatabaseIfNotExists 初始化程序)的那一刻,整个事情都过去了砰。

我之所以让EntityFrameworkUnitOfWork 扩展DbContext 主要是因为IUnitOfWork 包含EntityFrameworkUnitOfWork(或其他提供者)需要实现的所有存储库。我最初没有这样做,但我推断我是从模型中删除 DAL,而不是从 DAL 中删除模型 - 而且在 IUnitOfWork 对象上拥有属性来获取我需要的存储库会容易得多。

你有什么建议吗?

添加对 EntityFramework 的引用确实可以解决问题,但这也意味着当我的主项目根本不使用 EntityFramework 时,我必须添加对它的引用!

编辑:更新!我设法让它工作,但只能通过向我的项目添加 EntityFramework 引用。我创建了一个名为EntityFrameworkContext 的新类,其中包含DbSet&lt;T&gt;,它是在创建EntityFrameworkUnitOfWork 时创建的(它的静态构造函数中有一个初始化程序)。我想这个问题可以归结为:

假设有 EF 层的项目是 Project A。 注入层的项目是项目B。

我怎样才能在项目 A 上设置 EntityFramework(大概在它的 App.config 中),以便项目 B 在其配置中不需要引用 EntityFramework? 整个想法是,该层应该可以与其他一些项目(比如说 NHibernate 或 ActiveRecord)交换,我不需要修改我的主项目来占用这些修改。此外,项目 A 根本不直接引用 EntityFramework - 引用它是没有意义的。

【问题讨论】:

  • 我没用过结构图。但是,如果存储库位于 DAL.DLL 而不是 MainProject.DLL 中,则 MainProject.DLL 将不需要 EntityFramework.DLL。也许您只需将存储库移动到它们自己的程序集中。
  • 看到这就是我的想法,@P.Brian.Mackey。有3个项目。 DAL(包含接口)、EntityFrameworkProvider(包含实体框架相关的东西和 DAL 的实现)和 Main(IOC 解析器、主要方法等)。 Main 抱怨没有对 EntityFramework.dll 的引用,即使 EF 从未从 Main 中引用。
  • 听起来您需要添加一些 DTO。我敢打赌,您正在将 DAL 中的一些实体返回到上层(主)。通过返回自定义类 (DTO) 将它们抽象出来。就像属性包一样,“业务层”类型而不是 DAL 层类型。
  • @P.Brian.Mackey 如果您想查看代码,我们非常欢迎您 :) github.com/DanPantry/card-game。您将在 CardGame.Models 中找到模型,在 CardGame.DataAccess 中找到 DAL,在 CardGame.EntityFrameworkProvider 中找到 EntityFrameworkProvider,在 CardGame.Server 中找到 Main。您可能需要稍等一下,因为我目前正在推动。
  • 那个链接没有代码

标签: c# entity-framework dependency-injection inversion-of-control structuremap


【解决方案1】:

如果问题出在这一行

x.For<CardGame.DataAccess.IUnitOfWork>().Use(new CardGame.EntityFrameworkProvider.EntityFrameworkUnitOfWork("MyConnectionString"));

那么您可能应该考虑使用registry。这样,您可以在项目中拥有一个引用 EntityFramework 的注册表,如下所示:

public class MyProjectRegistry : Registry
{
    public MyProjectRegistry()
    {
        For<CardGame.DataAccess.IUnitOfWork>().Use(new CardGame.EntityFrameworkProvider.EntityFrameworkUnitOfWork("MyConnectionString"));
    }
}

由于您的 ObjectFactory 已经配置为查找注册表,这应该足以让它工作。

【讨论】:

  • 我会试一试,等一下。我预见到的唯一问题是,这意味着提供者必须“了解” StructureMap。这也意味着连接字符串名称必须存储在 EntityFrameworkProvider 项目中(除非有不同的方式?配置不是我的强项)
  • 你是对的,提供者需要一个对 StructureMap 的引用。这也意味着您拥有可在项目中重复使用的自配置程序集(如果您有此需要)。如果您通过构造函数注入构建所有内容,尽管它应该是您在程序集中唯一使用 StructureMap 的地方。
  • 是的。我只是设置它,它就像一个梦一样工作。现在我需要弄清楚如何将连接字符串传递给 EntityFrameworkProvider 中的注册表,但这完全是配置和不同的问题。感谢您的帮助!
猜你喜欢
  • 2011-04-27
  • 2011-09-14
  • 1970-01-01
  • 2014-04-29
  • 2011-01-02
  • 1970-01-01
  • 1970-01-01
  • 2011-08-04
  • 1970-01-01
相关资源
最近更新 更多