使用EF DbContext实现2个接口的dependency injection
给定一个实现2个接口的DbContext,如下所示:
public interface IQueryEntities { IQueryable Users { get; } IQueryable Computers { get; } // other IQueryable get properties } public interface IUnitOfWork { int SaveChanges(); } public class MyContext : DbContext, IQueryEntities, IUnitOfWork { // implement interfaces using EF }
第一个问题,从命令方面(SaveChanges)中分离出DbContext(IDbSets)的查询方面是一个坏主意吗? 我正在探索上面的重构,因为在很多情况下我们只需要查询数据,而不保存任何内容。
我遇到的问题涉及统一DI,它目前使用IUnitOfWork接口的单个每个http上下文生命周期注入MyDbContext。 我不确定如何为IQueryEntities接口设置注入,以便它可以重用已经针对IUnitOfWork接口注入的现有DbContext实例。 或相反亦然。 这有可能吗?
这是当前的生命周期管理器,它在同一个http上下文中重用以前注入的IUnitOfWork实例:
public class UnityHttpContextLifetimeManager : LifetimeManager { private const string KeyFormat = "SingletonPerCallContext_{0}"; private readonly string _key; public UnityHttpContextLifetimeManager() { _key = string.Format(KeyFormat, Guid.NewGuid()); } public override object GetValue() { return HttpContext.Current.Items[_key]; } public override void SetValue(object newValue) { HttpContext.Current.Items[_key] = newValue; } public override void RemoveValue() { HttpContext.Current.Items.Remove(_key); } }
顺便说一句,如果有办法做到这一点,我宁愿在统一web.config部分而不是编译c#bootstrapper。
更新
在onof的帮助下,我能够使这个工作,但我的配置看起来与他的建议不同。 难道我做错了什么? 当我没有为每个接口提供生命周期管理器时,一个HttpContext最终会有DbContext的多个实例。 只有当我给所有3个生命周期管理器时,它才会在两个接口的单个请求中重用相同的DbContext实例。 这个配置有问题吗?
...
从命令方面(SaveChanges)中分离出DbContext(IDbSets)的查询方面是不是一个坏主意?
我认为这是一个好主意,因为接口隔离原则指出每个客户端应该只看到它所需的接口才能完成其工作。
要注册,我会这样做:
container.RegisterType(new UnityHttpContextLifetimeManager()); container.RegisterType(); container.RegisterType();
AFAIK是创建对象后共享同一实例的唯一方法。
要在设计时(在web.config中)执行此操作,它很简单:
您需要将一个接口注册为单例,另一个接口将自动跟随。
container.RegisterType(new UnityHttpContextLifetimeManager()); container.RegisterType();
假设您的LifetimeManager正常工作,这会将MyContext
实例的生命周期范围MyContext
为HttpContext
,而IUnitOfWork
的映射将重用相同的实例,因为映射的目标是相同的。