我正在尝试实现一个存储库模式,但遇到了我的上下文的困难。当我按照预期开始调试我的UI显示时,所有数据都会按原样返回,但是当我尝试过滤数据时,我从EF获得异常,通知我“已经有一个与此命令关联的开放DataReader ......”
init
我的存储库界面如下所示:
public static class UnityConfig
{
public static UnityContainer Container;
public static void RegisterComponents()
{
var container = new UnityContainer();
Container = container;
// register all your components with the container here
// it is NOT necessary to register your controllers
container.RegisterType<DbContext, ApplicationDbContext>(new HierarchicalLifetimeManager());
container.RegisterType<MyContext>(new PerRequestLifetimeManager());
container.AddNewExtension<RepositoryModule>();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
}
public class RepositoryModule : UnityContainerExtension
{
protected override void Initialize()
{
Container.RegisterType<IBusinessClass>(
new PerRequestLifetimeManager()),
new InjectionFactory(
c => new BusinessClass
c.Resolve<IRepository<EntityOne>>(),
c.Resolve<IRepository<EntityTwo>>());
);
Container.RegisterType<IRepository<EntityOne>, RepoOne>(
new PerRequestLifetimeManager(),
new InjectionFactory(
c => new RepoOne(c.Resolve<MyContext>())));
Container.RegisterType<IRepository<EntityTwo>, RepoTwo>(
new PerRequestLifetimeManager(),
new InjectionFactory(
c => new RepoTwo(c.Resolve<MyContext>())));
}
}
存储库的实现使用了一个抽象类来保存和处理功能:
public interface IRepository<T> where T : class
{
IQueryable<T> Query { get; }
T GetByID(int id);
IEnumerable<T> GetAll();
T Insert(T entity);
void Update(T entity);
void Delete(T entity);
void Save();
}
实际的存储库看起来像这样:
public abstract class BaseRepository : IDisposable
{
protected MyContext context;
protected BaseRepository(MyContext context)
{
this.context = context;
}
/// <summary>
/// Save changes
/// </summary>
public void Save()
{
context.SaveChanges();
}
#region Dispose
private bool disposed = false;
protected virtual void Dispose(bool diposing)
{
if (!disposed)
{
context.Dispose();
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
我假设我的背景没有被处理,但我无法弄清楚原因。我错过了什么或者我完全搞砸了这里的建筑吗?
[编辑] 代码正在处理第一次加载。只有当我回到存储库才能获得我遇到问题的过滤后的数据子集时。
我已经更新了解决方案,使用一个简单的工厂来获取存储库,因此Unity中的分配现在看起来像这样:
public class RepoOne : BaseRepository, IRepository<EntityOne>
{
public RepoOne(MyContext context)
: base(context)
{
this.context = context;
}
public IQueryable<EntityOne> Query => context.EntityOne;
public EntityOne GetByID(int id)
{
return context.EntityOne.Find(id);
}
public IEnumerable<EntityOne> GetAll()
{
return context.EntityOne.ToList();
}
public EntityOne Insert(EntityOne entity)
{
return context.EntityOne.Add(entity);
}
public void Update(EntityOne entity)
{
var entityOne = context.EntityOne.Find(entity.ID);
}
public void Delete(EntityOne entity)
{
throw new NotImplementedException();
}
}
和工厂:
Container.RegisterType<IRepository<EntityOne>>(
new PerRequestLifetimeManager(),
new InjectionFactory(
c =>
RepositoryFactory<EntityOne>.GetRepository(
"EntityOne",
c.Resolve<MyContext>())));
@vendettamit:我的PerRequestLifetimeManager
public static class RepositoryFactory<T> where T : class
{
public static IRepository<T> GetRepository(string entityType, PollBookMonitorContext context)
{
switch (entityType)
{
case "EntityOne":
return (IRepository<T>) new RepoOne(context);
case "EntityTwo":
return (IRepository<T>) new RepoTwo(context);
default: return null;
}
非常感谢任何帮助。
我的代码终于有效了。我刚刚发现我查询的其中一个表是整天都在处理大量数据,据我所知,这会导致EF从数据库中读取数据的方式产生负面影响。或许我在没注意的时候解决了这个问题。
答案 0 :(得分:1)
我认为问题在于:
private bool disposed = false;
protected virtual void Dispose(bool diposing)
{
if (!disposed)
{
context.Dispose();
}
}
在if而不是使用全局字段中,使用参数&#34; disposing&#34;
protected virtual void Dispose(bool diposing)
{
if (!disposing) return;
context.Dispose();
}
答案 1 :(得分:1)
使用PerRequestLifetimeManager
需要注册UnityPerRequestHttpModule
。根据{{3}},
对于HTTP请求完成时自动处理的注册类型的实例,请确保将UnityPerRequestHttpModule注册到Web应用程序。
检查UnityConfig.cs,确保它没有注册模块。模块注册应在Unity.Mvc.Activator.cs
中完成。或者,您也可以尝试在启动文件(OWIN)中注册模块:
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(UnityWebActivator), "Start")]
答案 2 :(得分:1)
您应该执行以下操作:
public interface IRepository : IDisposable
{
// Your code.
}
然后在您的数据上下文中,它将实现您的部署:
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if(!disposed)
{
if(disposing)
{
component.Dispose();
}
disposed = true;
}
}
~DataContext() { Dispose(false); }
如果你真的想要,你可以稍微清理一下你的架构。你可以做的一种方法就是这样:
public interface IRepository
{
// Your method operation.
}
public interface IFactory : IRepositoryFactory
{
// Container factory, to interject between multiple data context.
}
public interface IRepositoryFactory
{
IRepository Create();
}
public class DataContext : DbContext, IRepository
{
// Entity Framework and Repository concreete implementation.
}
public class DataContextFactory : IFactory
{
public IRepository Create()
{
return new DataContext();
}
}
然后,您将使用Unity映射工厂,然后您只需在方法中调用:
using(var context = Create())
return context.List<Model>(....);