我試圖實現存儲庫模式,但遇到了與上下文有關的困難。當我開始調試我的UI顯示時,正如我所期望的那樣,所有的數據都會像它應該那樣返回,但是當我嘗試過濾數據時,我從EF那裏得到異常,通知我「已經有一個與此命令關聯的打開的DataReader ...」使用Unity時EF上下文不會處理
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
}
個實際存儲庫是這樣的:
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>())));
和工廠:
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;
}
@vendettamit:我的PerRequestLifetimeManager
public class PerRequestLifetimeManager : LifetimeManager
{
private readonly object key = new object();
public override object GetValue()
{
if (HttpContext.Current != null &&
HttpContext.Current.Items.Contains(key))
return HttpContext.Current.Items[key];
return null;
}
public override void SetValue(object newValue)
{
if (HttpContext.Current != null)
HttpContext.Current.Items[key] = newValue;
}
public override void RemoveValue()
{
if (HttpContext.Current != null)
HttpContext.Current.Items.Remove(key);
}
}
任何幫助,非常感謝。
我的代碼終於工作了。我剛剛發現,我查詢的其中一個表格是整天都在處理大量數據,並且據我所知,這對EF從數據庫中讀取的方式造成了不利影響。或者,當我不注意時,我可能會解決這個問題。
你確定這是不是處置? – Greg
我假設異常消息指出已經有一個與命令關聯的打開的數據讀取器意味着上下文尚未處理。 – crunchy
@crunchy不需要處理......問題是指在同一個上下文中同時查詢多個數據(也許兩個不同的http請求獲取相同的上下文對象?)...生命週期上下文對象不是很重要(你可以不經過處理就傳遞),實際查詢的生命週期是(特別是在多線程場景中)。你確定你的'PerRequestLifetimeManager'實現正在做它應該做的事嗎? – Jcl