这是来自ANTS内存分析器的图像。它认为内存中有很多对象。我怎样才能找到我做错的事?
**UPDATE**
这是我的存储库类:
public class Repository<T> : IRepository<T> where T : class, IDataEntity
{
ObjectContext _context;
IObjectSet<T> _objectSet;
readonly string _entitySetName;
readonly string[] _keyNames;
private ObjectContext Context
{
get
{
if (_context == null)
{
_context = GetCurrentUnitOfWork<EFUnitOfWork>().Context;
}
return _context;
}
}
private IObjectSet<T> ObjectSet
{
get
{
if (_objectSet == null)
{
_objectSet = this.Context.CreateObjectSet<T>();
}
return _objectSet;
}
}
public TUnitOfWork GetCurrentUnitOfWork<TUnitOfWork>() where TUnitOfWork : IUnitOfWork
{
return (TUnitOfWork)UnitOfWork.Current;
}
public virtual IEnumerable<T> GetQuery()
{
return ObjectSet;
}
public virtual IEnumerable<T> GetQuery(params Expression<Func<T, object>>[] includes)
{
return ObjectSet.IncludeMultiple(includes);
}
public virtual IEnumerable<T> GetQuery(
IEnumerable<Expression<Func<T, bool>>> filters,
Func<IQueryable<T>, IOrderedQueryable<T>> orderBy,
IEnumerable<Expression<Func<T, object>>> includes)
{
IQueryable<T> _query = ObjectSet;
if (filters != null)
{
foreach (var filter in filters)
{
_query = _query.Where(filter);
}
}
if (includes != null && includes.Count() > 0)
{
_query = _query.IncludeMultiple(includes.ToArray());
}
if (orderBy != null)
{
_query = orderBy(_query);
}
return _query;
}
public virtual IPaged<T> GetQuery(
IEnumerable<Expression<Func<T, bool>>> filters,
Func<IQueryable<T>, IOrderedQueryable<T>> orderBy,
int pageNumber, int pageSize,
IEnumerable<Expression<Func<T, object>>> includes)
{
IQueryable<T> _query = ObjectSet;
if (filters != null)
{
foreach (var filter in filters)
{
_query = _query.Where(filter);
}
}
if (orderBy != null)
{
_query = orderBy(_query);
}
IPaged<T> page = new Paged<T>(_query, pageNumber, pageSize, includes);
return page;
}
public virtual void Insert(T entity)
{
this.ObjectSet.AddObject(entity);
}
public virtual void Delete(T entity)
{
if (entity is ISoftDeletable)
{
((ISoftDeletable)entity).IsDeleted = true;
//Update(entity);
}
else
{
this.ObjectSet.DeleteObject(entity);
}
}
public virtual void Attach(T entity)
{
ObjectStateEntry entry = null;
if (this.Context.ObjectStateManager.TryGetObjectStateEntry(entity, out entry) == false)
{
this.ObjectSet.Attach(entity);
}
}
public virtual void Detach(T entity)
{
ObjectStateEntry entry = null;
if (this.Context.ObjectStateManager.TryGetObjectStateEntry(entity, out entry) == true)
{
this.ObjectSet.Detach(entity);
}
}
}
现在,如果我有A类来保存表A中的记录,我也创建了类:
public class ARepository:BaseRepository<A> {
// Implementation of A's queries and specific db operations
}
这是我的EFUnitOfWork课程:
public class EFUnitOfWork : IUnitOfWork, IDisposable
{
public ObjectContext Context { get; private set; }
public EFUnitOfWork(ObjectContext context)
{
Context = context;
context.ContextOptions.LazyLoadingEnabled = true;
}
public void Commit()
{
Context.SaveChanges();
}
public void Dispose()
{
if (Context != null)
{
Context.Dispose();
}
GC.SuppressFinalize(this);
}
}
和UnitOfWork类:
public static class UnitOfWork
{
private const string HTTPCONTEXTKEY = "MyProj.Domain.Business.Repository.HttpContext.Key";
private static IUnitOfWorkFactory _unitOfWorkFactory;
private static readonly Hashtable _threads = new Hashtable();
public static void Commit()
{
IUnitOfWork unitOfWork = GetUnitOfWork();
if (unitOfWork != null)
{
unitOfWork.Commit();
}
}
public static IUnitOfWork Current
{
get
{
IUnitOfWork unitOfWork = GetUnitOfWork();
if (unitOfWork == null)
{
_unitOfWorkFactory = ObjectFactory.GetInstance<IUnitOfWorkFactory>();
unitOfWork = _unitOfWorkFactory.Create();
SaveUnitOfWork(unitOfWork);
}
return unitOfWork;
}
}
private static IUnitOfWork GetUnitOfWork()
{
if (HttpContext.Current != null)
{
if (HttpContext.Current.Items.Contains(HTTPCONTEXTKEY))
{
return (IUnitOfWork)HttpContext.Current.Items[HTTPCONTEXTKEY];
}
return null;
}
else
{
Thread thread = Thread.CurrentThread;
if (string.IsNullOrEmpty(thread.Name))
{
thread.Name = Guid.NewGuid().ToString();
return null;
}
else
{
lock (_threads.SyncRoot)
{
return (IUnitOfWork)_threads[Thread.CurrentThread.Name];
}
}
}
}
private static void SaveUnitOfWork(IUnitOfWork unitOfWork)
{
if (HttpContext.Current != null)
{
HttpContext.Current.Items[HTTPCONTEXTKEY] = unitOfWork;
}
else
{
lock(_threads.SyncRoot)
{
_threads[Thread.CurrentThread.Name] = unitOfWork;
}
}
}
}
以下是我如何使用它:
public class TaskPriceRepository : BaseRepository<TaskPrice>
{
public void Set(TaskPrice entity)
{
TaskPrice taskPrice = GetQuery().SingleOrDefault(x => x.TaskId == entity.TaskId);
if (taskPrice != null)
{
CommonUtils.CopyObject<TaskPrice>(entity, ref taskPrice);
}
else
{
this.Insert(entity);
}
}
}
public class BranchRepository : BaseRepository<Branch>
{
public IList<Branch> GetBranchesList(Guid companyId, long? branchId, string branchName)
{
return Repository.GetQuery().
Where(b => companyId == b.CompanyId).
Where(b => b.IsDeleted == false).
Where(b => !branchId.HasValue || b.BranchId.Equals(branchId.Value)).
Where(b => branchName == null || b.BranchName.Contains(branchName)).
ToList();
}
}
[WebMethod]
public void SetTaskPrice(TaskPriceDTO taskPrice)
{
TaskPrice tp = taskPrice.ToEntity();
TaskPriceRepository rep = new TaskPriceRepository();
rep.Set(tp);
UnitOfWork.Commit();
}
[WebMethod]
public IList<Branch> GetBranchesList()
{
BranchRepository rep = new BranchRepository();
return rep.GetBranchesList(m_User.UserCompany.CompanyId, null, null).ToList();
}
我希望这足以帮助我解决问题。感谢。
UPDATE 2
还有UnitOfWorkFactory初始化UnitOfWork:
public class UnitOfWorkFactory : IUnitOfWorkFactory
{
private static Func<ObjectContext> _objectContextDelegate;
private static readonly Object _lockObject = new object();
public static void SetObjectContext(Func<ObjectContext> objectContextDelegate)
{
_objectContextDelegate = objectContextDelegate;
}
public IUnitOfWork Create()
{
ObjectContext context;
lock (_lockObject)
{
context = _objectContextDelegate();
}
return new EFUnitOfWork(context);
}
}
为了使用它,在应用程序启动时我使用了structuremap:
ObjectFactory.Initialize(x =>
{
x.For<IUnitOfWorkFactory>().Use<UnitOfWorkFactory>();
x.For(typeof(IRepository<>)).Use(typeof(Repository<>));
});
答案 0 :(得分:14)
我有预感你没有处理上下文
我建议你在与数据库交互时处理上下文。
创建上下文时使用using
语句。
<强> [编辑] 强>
据我所见,您缓存并且不会处置您的EFUnitOfWork
对象。它是一次性的,这是正确的,但我没有看到什么时候被称为一次性。似乎你对所有应用程序运行时的上下文都有一个引用。
而且,你为每个线程创建并保存一个上下文,这会使它更糟。
我无法确定您应该将Dispose
或using
放在哪里,因为我不知道这些用法。
您可以将它放在Commit
方法中,但我不知道Commit
在数据库交互会话期间是否只调用过一次。
此外,您的设计可能过于复杂。
如果我是你,我会:
如果我有时间,我会立即做出长期解决方案
但同样,我无法判断您的设计是否合理,因为我不知道您的应用程序有多大,它的功能和要求是什么。
答案 1 :(得分:5)
我想到了一些事情:
using(var context = CreateObjectContext())
块from customer in context.Customers select customer
之类的查询,而不是from customer in context.Customers select customer.FirstOrDefault()
我很难让Entity Framework在N层应用程序中工作。它不适合在N层应用程序中使用。只有EF 4.0。您可以阅读我在使用N层应用程序制作EF 3时的所有冒险经历。
http://www.codeproject.com/KB/linq/ef.aspx
这会回答你的问题吗?
答案 2 :(得分:3)
您偶尔会清除ObjectContext
吗?如果长时间保持ObjectContext
处于活动状态,则会占用与EntityDataModel大小相关的内存以及加载到此ObjectContext
中的实体数。
答案 3 :(得分:0)
在使用依赖注入的类中,我遇到了同样的问题,因此using()
选项不是替代选择。我的解决方案是将DbContextOptions<Context>
添加到构造函数中,并将其作为私有字段添加到类中。然后,您可以致电
_db.Dispose();
_db = new BlockExplorerContext(_dBContextOptions);
在适当的时间。这解决了我内存不足,应用程序被操作系统杀死的问题。