IOC容器试图引用DbContext

时间:2013-12-05 15:29:37

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

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

EntityFrameworkRepository.cs

CardGame.EntityFrameworkProvider

EntityFrameworkUnitofWork.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);
    }
}

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

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();
    }
}

我的问题是, 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(包含Main.cs的项目)无法编译,因为它没有(故意)包含对EntityFramework的引用。我试图尽可能地将其作为数据库不可知,并且到目前为止它已经很顺利,但是当我CardGame.Server延长EntityFrameworkUnitOfWork时(因此我可以应用DbContext初始值设定项),整个事情都爆炸了。

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

你有什么建议吗?

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

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

假设EF层的项目是项目A. 注入了层的项目是项目B.

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

1 个答案:

答案 0 :(得分: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已经配置为查找注册表,因此这应该足以让它工作。