C# IOC容器正在尝试引用DbContext
我正在编写一个程序,它将StructureMap用作IOC容器。 我已经实现了两个接口-C# IOC容器正在尝试引用DbContext,c#,entity-framework,dependency-injection,inversion-of-control,structuremap,C#,Entity Framework,Dependency Injection,Inversion Of Control,Structuremap,我正在编写一个程序,它将StructureMap用作IOC容器。 我已经实现了两个接口-IUnitOfWork和IDataAccessRepository,它们在运行时通过以下类(它们位于各自的项目-CardGame.EntityFrameworkProvider中)进行解析 EntityFrameworkRepository.cs public class EntityFrameworkRepository<T> : IDataAccessRepository<T>
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);
}
}
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();
}
}
公共类EntityFrameworkRepository:IDataAccessRepository
T:在哪里上课
{
私有dbcontextu ctx;
专用数据库集;
内部EntityFrameworkRepository(DbContext ctx)
{
_ctx=ctx;
set=_ctx.set();
}
公共可数元素
{
获取{返回集;}
}
公共T获取(int id)
{
返回set.Find(id);
}
公共无效添加(T)
{
增加(t);
}
公共无效更新(T)
{
设置。附加(t);
_ctx.Entry(t).State=EntityState.Modified;
}
公共作废删除(T)
{
if(_ctx.Entry(t.State==EntityState.Detached)
设置。附加(t);
设置。移除(t);
}
}
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);
}
}
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();
}
}
公共类EntityFrameworkUnitOfWork:DbContext,IUnitOfWork
{
///
///创建EntityFrameworkUnitOfWork。
///
///
public EntityFrameworkUnitOfWork(字符串connectionStringOrName):基(connectionStringOrName)
{
SetInitializer(新的DropCreateDatabaseIfModelChanges());
生物=新EntityFrameworkRepository(此);
MagicCards=新的EntityFrameworkRepository(此);
EffectDescriptors=新EntityFrameworkRepository(此);
}
#区域存储库
公共知识库生物
{
得到;
私人设置;
}
公共IDataAccessRepository MagicCards
{
得到;
私人设置;
}
公共IDataAccessRepository效应描述符
{
得到;
私人设置;
}
#端区
public new void SaveChanges()
{
base.SaveChanges();
}
}
最后,在我的主要方法中——在另一个项目中——我使用StructureMap将依赖项绑定在一起。
Main
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
});
ObjectFactory.Configure(x=>
{
x、 扫描(扫描=>
{
scan.LookForRegistries();
扫描程序集(“CardGame.DataAccess”);
扫描程序集(“CardGame.EntityFrameworkProvider”);
});
#区域持久性
x、 For().Use(new CardGame.EntityFrameworkProvider.EntityFrameworkUnitOfWork(“MyConnectionString”));
#端区
});
我的问题是,随着EntityFrameworkUnitOfWork
扩展DbContext
,我的CardGame.Server
(包含Main.cs的项目)无法编译,因为它(有意)不包含对EntityFramework的引用。我试图使其尽可能与数据库无关,到目前为止进展顺利,但当我制作了EntityFrameworkUnitOfWork
extendDbContext
(这样我就可以应用DropCreateDatabaseIfNotExists
初始值设定项)时,整个事情发生了
我之所以使用EntityFrameworkUnitOfWork
extendDbContext
主要是因为IUnitOfWork
包含EntityFrameworkUnitOfWork
需要实现的所有存储库。我最初没有这样做,但我推断我正在从模型中删除DAL,而不是从DAL中删除模型-而且在IUnitOfWork
对象上拥有属性以获取我需要的存储库会容易得多
你有什么建议吗
添加对EntityFramework的引用确实解决了这个问题,但这也意味着当EntityFramework根本不使用时,我必须将对EntityFramework的引用添加到我的主项目中
编辑:更新!我设法让它工作,但只是通过向我的项目添加EntityFramework引用。我创建了一个名为EntityFrameworkContext
的新类,其中包含DbSet
,该类是在创建EntityFrameworkUnitOfWork
时创建的(它的静态构造函数中有一个初始值设定项)。我想这个问题可以归结为:
假设具有EF层的项目是项目A。
将层注入其中的项目为项目B
如何在项目A上设置EntityFramework(可能在它的App.config中),以便项目B不需要在其配置中引用EntityFramework?
整个想法是该层应该可以与其他项目交换(比如NHibernate或ActiveRecord),我不需要修改我的主项目来占用这些修改。此外,项目A根本不直接引用EntityFramework——它引用它是没有意义的。如果问题是这一行
x.For<CardGame.DataAccess.IUnitOfWork>().Use(new CardGame.EntityFrameworkProvider.EntityFrameworkUnitOfWork("MyConnectionString"));
x.For().Use(新的CardGame.EntityFrameworkProvider.EntityFrameworkUnitOfWork(“MyConnectionString”);
那么你可能应该考虑使用一个。通过这种方式,您可以在项目中拥有一个注册表,该注册表引用EntityFramework,如下所示:
public class MyProjectRegistry : Registry
{
public MyProjectRegistry()
{
For<CardGame.DataAccess.IUnitOfWork>().Use(new CardGame.EntityFrameworkProvider.EntityFrameworkUnitOfWork("MyConnectionString"));
}
}
公共类MyProjectRegistry:注册表
{
公共MyProjectRegistry()
{
For().Use(new CardGame.EntityFrameworkProvider.EntityFrameworkUnitOfWork(“MyConnectionString”));
}
}
由于您的ObjectFactory已经配置为查找注册表,这应该足以使其正常工作。如果问题是这一行
x.For<CardGame.DataAccess.IUnitOfWork>().Use(new CardGame.EntityFrameworkProvider.EntityFrameworkUnitOfWork("MyConnectionString"));
x.For().Use(新的CardGame.EntityFrameworkProvider.EntityFrameworkUnitOfWork(“MyConnectionString”);
那么你可能应该考虑使用一个。通过这种方式,您可以在项目中拥有一个注册表,该注册表引用EntityFramework,如下所示:
public class MyProjectRegistry : Registry
{
public MyProjectRegistry()
{
For<CardGame.DataAccess.IUnitOfWork>().Use(new CardGame.EntityFrameworkProvider.EntityFrameworkUnitOfWork("MyConnectionString"));
}
}
公共类MyProjectRegistry:注册表
{
公共MyProjectRegistry()
{