日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

在WebApi項(xiàng)目上使用Unity依賴注入時(shí),將處置DbContext

 印度阿三17 2019-10-25

我在使用依賴注入方面還很陌生,我認(rèn)為我必須忽略一些非常簡單的事情.

我有一個(gè)Web API項(xiàng)目,在這里注冊(cè)通用存儲(chǔ)庫.存儲(chǔ)庫在其構(gòu)造函數(shù)中將dbContext作為參數(shù).

我發(fā)現(xiàn)很奇怪的行為是,我可以對(duì)服務(wù)進(jìn)行一次成功調(diào)用,但是隨后的任何調(diào)用都告訴我dbcontext已被處置.我確實(shí)有一個(gè)using語句,但這應(yīng)該不是問題,因?yàn)镈I應(yīng)該為每個(gè)Web請(qǐng)求創(chuàng)建依賴項(xiàng)的新實(shí)例(盡管我可能錯(cuò)了).

這是我的通用存儲(chǔ)庫:

 public class GenericRepository<T> : IGenericRepository<T> where T : class
{
    internal DbContext _context;
    internal DbSet<T> _dbSet;
    private bool disposed;

    public GenericRepository(DbContext context)
    {
        _context = context;
        _dbSet = _context.Set<T>();
    }

    /// <summary>
    /// This constructor will set the database of the repository 
    /// to the one indicated by the "database" parameter
    /// </summary>
    /// <param name="context"></param>
    /// <param name="database"></param>       
    public GenericRepository(string database = null)
    {
        SetDatabase(database);
    }

    public void SetDatabase(string database)
    {
        var dbConnection = _context.Database.Connection;
        if (string.IsNullOrEmpty(database) || dbConnection.Database == database)
            return;

        if (dbConnection.State == ConnectionState.Closed)
            dbConnection.Open();

        _context.Database.Connection.ChangeDatabase(database);
    }

    public virtual IQueryable<T> Get()
    {
        return _dbSet;
    }

    public virtual T GetById(object id)
    {
        return _dbSet.Find(id);
    }

    public virtual void Insert(T entity)
    {
        _dbSet.Add(entity);
    }

    public virtual void Delete(object id)
    {
        T entityToDelete = _dbSet.Find(id);
        Delete(entityToDelete);
    }

    public virtual void Delete(T entityToDelete)
    {
        if (_context.Entry(entityToDelete).State == EntityState.Detached)
        {
            _dbSet.Attach(entityToDelete);
        }

        _dbSet.Remove(entityToDelete);
    }

    public virtual void Update(T entityToUpdate)
    {
        _dbSet.Attach(entityToUpdate);
        _context.Entry(entityToUpdate).State = EntityState.Modified;
    }

    public virtual void Save()
    {
        _context.SaveChanges();
    }
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposed)
            return;

        if (disposing)
        {
            //free managed objects here
            _context.Dispose();
        }

        //free any unmanaged objects here
        disposed = true;
    }

    ~GenericRepository()
    {
        Dispose(false);
    }
}

這是我的通用存儲(chǔ)庫接口:

 public interface IGenericRepository<T> : IDisposable where T : class
{
    void SetDatabase(string database);
    IQueryable<T> Get();       
    T GetById(object id);
    void Insert(T entity);
    void Delete(object id);
    void Delete(T entityToDelete);
    void Update(T entityToUpdate);
    void Save();
}

這是我的WebApiConfig:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services
        var container = new UnityContainer();

        container.RegisterType<IGenericRepository<Cat>, GenericRepository<Cat>>(new HierarchicalLifetimeManager(), new InjectionConstructor(new AnimalEntities()));
        container.RegisterType<IGenericRepository<Dog>, GenericRepository<Dog>>(new HierarchicalLifetimeManager(), new InjectionConstructor(new AnimalEntities()));           

        config.DependencyResolver = new UnityResolver(container);

        config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));

        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}

這是我的DependencyResolver(非常標(biāo)準(zhǔn)):

public class UnityResolver : IDependencyResolver
{
    protected IUnityContainer container;

    public UnityResolver(IUnityContainer container)
    {
        this.container = container ?? throw new ArgumentNullException(nameof(container));
    }

    public object GetService(Type serviceType)
    {
        try
        {
            return container.Resolve(serviceType);
        }
        catch (ResolutionFailedException)
        {
            return null;
        }
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        try
        {
            return container.ResolveAll(serviceType);
        }
        catch (ResolutionFailedException)
        {
            return new List<object>();
        }
    }

    public IDependencyScope BeginScope()
    {
        var child = container.CreateChildContainer();
        return new UnityResolver(child);
    }

    public void Dispose()
    {
        Dispose(true);
    }

    protected virtual void Dispose(bool disposing)
    {
        container.Dispose();
    }
}

最后,這是給我?guī)砺闊┑目刂破鞯囊徊糠郑?/p>

public class AnimalController : ApiController
{
    private readonly IGenericRepository<Cat> _catRepo;
    private readonly IGenericRepository<Dog> _dogPackRepo;

    public AnimalController(IGenericRepository<Cat> catRepository,
        IGenericRepository<Dog> dogRepository)
    {
        _catRepo = catRepository;
        _dogRepo = dogRepository;
    }

    [HttpGet]
    public AnimalDetails GetAnimalDetails(int tagId)
    {
        var animalDetails = new animalDetails();

        try
        {
            var dbName = getAnimalName(tagId);

            if (dbName == null)
            {
                animalDetails.ErrorMessage = $"Could not find animal name for tag Id {tagId}";
                return animalDetails;
            }

        }
        catch (Exception ex)
        {
            //todo: add logging
            Console.WriteLine(ex.Message);
            animalDetails.ErrorMessage = ex.Message;
            return animalDetails;
        }

        return animalDetails;
    }

    private string getAnimalName(int tagId)
    {
        try
        {
            //todo: fix DI so dbcontext is created on each call to the controller
            using (_catRepo)
            {
                return _catRepo.Get().Where(s => s.TagId == tagId.ToString()).SingleOrDefault();
            }
        }
        catch (Exception e)
        {
            //todo: add logging
            Console.WriteLine(e);
            throw;
        }
    }       
}

_catRepo對(duì)象周圍的using語句行為不符合預(yù)期.在我進(jìn)行第一個(gè)服務(wù)調(diào)用后,_catRepo被處理掉了.在隨后的調(diào)用中,我希望實(shí)例化一個(gè)新的_catRepo.但是,情況并非如此,因?yàn)槲矣龅降腻e(cuò)誤是關(guān)于dbcontext被處置的.

我試圖將LifeTimeManager更改為其他可用的功能,但這無濟(jì)于事.

我也開始沿著另一條路線走,通用存儲(chǔ)庫將采用第二個(gè)通用類,并從中實(shí)例化其自己的dbcontext.但是,當(dāng)我這樣做時(shí),Unity找不到控制器的單參數(shù)構(gòu)造函數(shù).

我想,根據(jù)下面的評(píng)論,我真正需要的是一種基于每個(gè)請(qǐng)求實(shí)例化DbContext的方法.我不知道該怎么做.

任何提示將不勝感激.

解決方法:

讓我們來看看您的注冊(cè):

container.RegisterType<IGenericRepository<Cat>, GenericRepository<Cat>>(
    new HierarchicalLifetimeManager(), 
    new InjectionConstructor(new AnimalEntities()));

container.RegisterType<IGenericRepository<Dog>, GenericRepository<Dog>>(
    new HierarchicalLifetimeManager(), 
    new InjectionConstructor(new AnimalEntities()));

您將在啟動(dòng)時(shí)創(chuàng)建兩個(gè)AnimalEntities實(shí)例,但是這些實(shí)例在整個(gè)應(yīng)用程序期間將被重用.這是一個(gè)terrible idea.您可能打算擁有one DbContext per request,但是InjectionConstructor包裝的實(shí)例是一個(gè)常量.

您應(yīng)該將配置更改為以下內(nèi)容:

container.RegisterType<IGenericRepository<Cat>, GenericRepository<Cat>>(
    new HierarchicalLifetimeManager());

container.RegisterType<IGenericRepository<Dog>, GenericRepository<Dog>>(
    new HierarchicalLifetimeManager());

// Separate 'scoped' registration for AnimalEntities.
container.Register<AnimalEntities>(
    new HierarchicalLifetimeManager()
    new InjectionFactory(c => new AnimalEntities()));

這要簡單得多,現(xiàn)在AnimalEntities也已注冊(cè)為“作用域”.

這樣做的好處是,一旦作用域(Web請(qǐng)求)結(jié)束,Unity現(xiàn)在將處置AnimalEntities.這樣可以避免您必須對(duì)AnimalEntities的使用者實(shí)施IDisposable,如herehere所述.

來源:https://www./content-4-521101.html

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多