【发布时间】:2013-12-05 15:29:36
【问题描述】:
我现在正在编写一个程序,它使用 StructureMap 作为 IOC 容器。
我已经实现了几个接口 - IUnitOfWork 和 IDataAccessRepository,它们在运行时使用以下类解析(它们在他们自己的项目中 - 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<T>,它是在创建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