我知道发生了什么。正如一些人指出的那样,我的存储库不需要从IDisposable继承,因为Unity容器将在适当的时候处理这些存储库。然而,这并不是我问题的根源。
要克服的主要挑战是获得一个
dbContext
IGenericRepository
界面保持不变,但我的
GenericRepository
现在的实现如下所示:
public class GenericRepository<TDbSet, TDbContext> :
IGenericRepository<TDbSet> where TDbSet : class
where TDbContext : DbContext, new()
{
internal DbContext _context;
internal DbSet<TDbSet> _dbSet;
public GenericRepository(DbContext context)
{
_context = context;
_dbSet = _context.Set<TDbSet>();
}
public GenericRepository() : this(new TDbContext())
{
}
/// <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<TDbSet> Get()
{
return _dbSet;
}
public virtual TDbSet GetById(object id)
{
return _dbSet.Find(id);
}
public virtual void Insert(TDbSet entity)
{
_dbSet.Add(entity);
}
public virtual void Delete(object id)
{
TDbSet entityToDelete = _dbSet.Find(id);
Delete(entityToDelete);
}
public virtual void Delete(TDbSet entityToDelete)
{
if (_context.Entry(entityToDelete).State == EntityState.Detached)
{
_dbSet.Attach(entityToDelete);
}
_dbSet.Remove(entityToDelete);
}
public virtual void Update(TDbSet entityToUpdate)
{
_dbSet.Attach(entityToUpdate);
_context.Entry(entityToUpdate).State = EntityState.Modified;
}
public virtual void Save()
{
_context.SaveChanges();
}
}
默认构造函数现在负责创建新的
DbContext
数据库上下文
数据库上下文
为每个web请求创建。我通过使用
using
声明。我能够验证我不再得到关于
数据库上下文
在后续请求中处理。
我的
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, AnimalEntities>>(new HierarchicalLifetimeManager(), new InjectionConstructor());
container.RegisterType<IGenericRepository<Dog>, GenericRepository<Dog, AnimalEntities>>(new HierarchicalLifetimeManager(), new InjectionConstructor());
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 }
);
}
}
有一件事让我很痛苦,那就是我没有意识到我还得打电话给
InjectionConstructor
注入构造函数
一旦我跨过那个障碍,我就能够改变我下面的控制器。这里的主要区别是我不再使用
声明:
public class IntegrationController : ApiController
{
private readonly IGenericRepository<Cat> _catRepo;
private readonly IGenericRepository<Dog> _dogPackRepo;
public IntegrationController(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
{
return _catRepo.Get().Where(s => s.TagId ==
tagId.ToString()).SingleOrDefault();
}
catch (Exception e)
{
//todo: add logging
Console.WriteLine(e);
throw;
}
}
}