如何使用Unity注入dbContext [英] How to inject my dbContext with Unity

查看:181
本文介绍了如何使用Unity注入dbContext的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何使用Unity注入dbContext类?我不能只为其他普通"类创建接口吗?我应该如何处理RequestContext类以及UnityConfig的外观?

How do I inject my dbContext class using Unity? I can't just create a Interface like for my other "normal" classes? What should I do with my RequestContext class and what should my UnityConfig look like?

public class RequestContext : IdentityDbContext<User>
    {
        public RequestContext()
            : base("DefaultConnection", throwIfV1Schema: false)
        {
            Database.SetInitializer<RequestContext>(new CreateDatabaseIfNotExists<RequestContext>());
        }

        public DbSet<Request> Requests { get; set; }
        public DbSet<Record> Records { get; set; }



        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
            base.OnModelCreating(modelBuilder);
        }

        public static RequestContext Create()
        {
            return new RequestContext();
        }
    }

在我的存储库类中,我像这样使用它,但想注入:

In my Repository class i use it like this but want to inject instead:

 private RequestContext dbContext;
 private IUserRepository _userRepository;

 public RequestRepository(IUserRepository userRepository)
 {
      dbContext = new RequestContext();
      _userRepository = userRepository;
 }

推荐答案

我通常使用DbContextFactory解决此问题.这样一来,您就可以在需要时创建上下文,并在完成后对其进行处置.

I'm usually solving this with a DbContextFactory. This would allow you to create the context when needed and also dispose it when you're done.

public interface IDbContextFactory
{
    IdentityDbContext<User> GetContext();
}

public class DbContextFactory : IDbContextFactory
{
    private readonly IdentityDbContext<User> _context;

    public DbContextFactory()
    {
        _context = new RequestContext("ConnectionStringName");
    }

    public IdentityDbContext<User> GetContext()
    {
        return _context;
    }
}

该工厂可以轻松注入.您可以在此处看到更完整的示例:存储库模式通用应用程序

This factory can easily be injected. You can see a more complete example here: Repository Pattern universal application

在工厂中,您还可以选择在构造函数或方法中创建DbContext.使用Unity时,建议您在构造函数中做的尽可能少,因为Unity会为您解决整个链.这意味着将在每次解析存储库时创建DbContext.这将要求注入存储库的类还需要处理存储库(这又应处理DbContext),并且当两个类使用相同的存储库实例时会发生什么?显然,可以使用生命周期管理器和良好的编程习惯来解决此问题,但我发现在需要时仅打开和关闭上下文会更加优雅.

With the factory you will also have the option to create the DbContext in constructor or in the method. When using Unity I recommend you to do as little as possible in the constructor, as Unity will resolve the entire chain for you. This means that the DbContext will be created every time the repository is resolved. This would require the class that injects the repository also needs to dispose the repository (which in turn should dispose the DbContext), and what happens when two classes are using the same repository instance? This can obviously be solved with lifetimemanagers and good programming practices, but I find it more elegant to simply open and close the context when needed.

方法使用示例:

using (var context = _dbContextFactory.GenerateContext())
{
    return context.Requests.FirstOrDefault(x => x.Id == foo);
}

还有一个用于存储库的更完整示例:

And a more complete example for your repository:

public class RequestRepository
{
    private IDbContextFactory _contextFactory;

    public RequestRepository(IDbContextFactory contextFactory)
    {
        // DbContext will not be created in constructor, and therefore your repository doesn't have to implement IDisposable.
        _contextFactory= contextFactory;
    }

    public Request FindById(int id)
    {
         // Context will be properly disposed thanks to using.
        using (var context = _dbContextFactory.GenerateContext())
        {
            return context.Requests.FirstOrDefault(x => x.Id == id);
        }
    }
}

当您为上下文创建界面时,我也建议您将DbSet<T>更改为IDbSet<T>以简化单元测试. DbContext的接口示例.

And when you're creating your interface for your context I can also recommend you to change DbSet<T> to IDbSet<T> to allow easier unit testing. Example of interface for DbContext.

public interface IDbContext : IDisposable, IObjectContextAdapter
{
        IDbSet<Request> Requests { get; set; }
        IDbSet<Record> Records { get; set; }
        int SaveChanges();

        DbSet Set(Type entityType);
        DbSet<TEntity> Set<TEntity>() where TEntity : class;
}

如果您希望将DbContext注入构造函数中,还可以查看工作单元模式,它包装了DbContext并允许多个类在特定生存期内(例如请求)使用相同的上下文.有人可能会争辩说,EF已经实施了工作单元模式,但是我将这一讨论再作一次.这里有几个例子:

If your're looking to inject the DbContext in the constructor you could also take a look at the Unit of Work-pattern, which wraps the DbContext and allows several classes to use the same context over a specific lifetime (eg a request). One may argue that EF already implements the Unit of Work-pattern, but I leave that discussion for another time. Here's a couple of examples:

http://www.codeproject.com/Articles/741207/Repository-with-Unit-of-Work-IoC-and-Unit-Test

洋葱构架,工作单元和通用储存库模式

这篇关于如何使用Unity注入dbContext的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆