c# - 使用实现 2 个接口(interface)的 EF DbContext 进行依赖注入(inject)

标签 c# dependency-injection entity-framework-4.1 unity-container dbcontext

给定一个实现 2 个接口(interface)的 DbContext,如下所示:

public interface IQueryEntities
{
    IQueryable<User> Users { get; }
    IQueryable<Computer> Computers { get; }
    // other IQueryable<T> get properties
}

public interface IUnitOfWork
{
    int SaveChanges();
}

public class MyContext : DbContext, IQueryEntities, IUnitOfWork
{
    // implement interfaces using EF
}

第一个问题,将 DbContext (IDbSets) 的查询方面与命令方面 (SaveChanges) 分开是个坏主意吗?我正在探索对上述内容的重构,因为在很多情况下我们只需要查询数据而不保存任何内容。

我遇到的问题涉及 unity DI,它目前为 IUnitOfWork 接口(interface)使用 singleton-per-http-context 生命周期注入(inject) MyDbContext。我不确定如何为 IQueryEntities 接口(interface)设置注入(inject),以便它将重用可能已经针对 IUnitOfWork 接口(interface)注入(inject)的现有 DbContext 实例。或相反亦然。这可能吗?

这是当前生命周期管理器,它在相同的 http 上下文中重用先前注入(inject)的 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);
    }
}

顺便说一下,如果有办法做到这一点,我宁愿在 unity web.config 部分而不是编译的 c# Bootstrap 中进行。

更新

在 onof 的帮助下,我能够使它正常工作,但是我的配置看起来与他建议的不同。难道我做错了什么?当我不为每个接口(interface)提供生命周期管理器时,一个 HttpContext 将以 DbContext 的多个实例结束。只有当我给所有 3 个生命周期管理器时,它才会在对两个接口(interface)的单个​​请求中重用相同的 DbContext 实例。这个配置有问题吗?

<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <namespace name="MyApp.MyNameSpace" />
    <assembly name="MyApp" />
    <alias alias="singleton-per-http-context" 
        type="MyApp.MyNameSpace.UnityHttpContextLifetimeManager, MyApp" />
    <container>
        <register type="MyContext">
            <lifetime type="singleton-per-http-context" />
        </register>
        <register type="IUnitOfWork" mapTo="MyContext">
            <lifetime type="singleton-per-http-context" />
        </register>
        <register type="IQueryEntities" mapTo="MyContext">
            <lifetime type="singleton-per-http-context" />
        </register>
        ...
    </container>

最佳答案

is it a bad idea to separate out the query aspects of DbContext (IDbSets) from the command aspects (SaveChanges)?

我认为这是个好主意,因为 Interface Segregation Principle ,它指出每个客户端应该只看到它完成工作所需的界面。

要注册,我会这样做:

container.RegisterType<MyContext>(new UnityHttpContextLifetimeManager());
container.RegisterType<IQueryEntities, MyContext>();
container.RegisterType<IUnitOfWork, MyContext>();

据我所知,一旦对象创建,这是共享同一实例的唯一方法。

要在设计时(在 web.config 中)执行此操作,很简单:

<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <namespace name="MyApp.MyNameSpace" />
    <assembly name="MyApp" />
    <container>
      <register type="MyContext" >    
         <lifetime type="UnityHttpContextLifetimeManager" />
      </register>
      <register type="IQueryEntities" mapTo="MyContext" />
      <register type="IUnitOfWork" mapTo="MyContext" />
    </container>

关于c# - 使用实现 2 个接口(interface)的 EF DbContext 进行依赖注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9072339/

相关文章:

c# - 代码分析或代码审查的最佳工具

c# - 比较 2 个数据表以查找列之间的差异/准确性

entity-framework - 一对零/一关系(代码优先)

c# - 需要了解简短的 ASP.NET 源代码

c# - ASP.NET MVC3 VPS 托管 : Windows 2008 32bit or Windows 2008 R2?

c# - 向 Unity 注册类型以使用需要参数数组的构造函数

java - 使用或不使用 Spring Beans 有什么区别?

java - Spring 启动 : BeanFactoryPostProcessor's postProcessBeanFactory not getting called

asp.net-mvc-3 - 我应该如何在 MVC3 中使用 Code First Entity Framework (4.1) 声明外键关系?

.net - 如何在模型优先上调用 Database.SetInitializer?