2017-01-31 32 views
2

我们使用实体框架和存储库模式在MVC中开发了一个应用程序。当用户登录时,他们会根据他们的状态看到具有多次班次计数的仪表板。见下文:如何使用实体框架和存储库模式获得记录数

enter image description here

在控制器我们填充使用视图模型下面的行:

viewModel.shiftsInProgress = _shiftDateService.GetShiftDatesByStatusID(72).Count(); 

这指向以下方法:

public IList<ShiftDate> GetShiftDatesByStatusID(int statusID) 
    { 
     return _UoW.ShiftDates.Get(s => s.shiftDateStatusID == statusID) 
      .OrderByDescending(s => s.shiftID).ToList(); 
    } 

该方法也被用于在另一个视图中按状态列出轮班名单。

我们的工作(_UOW)单位被映射到其中包含2种get方法的通用存储库:

public IList<TEntity> Get(Expression<Func<TEntity, bool>> filter = null,Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,string includeProperties = "") 
    { 
     IQueryable<TEntity> query = dbSet; 

     if (filter != null) 
     { 
      query = query.Where(filter); 
     } 

     foreach (var includeProperty in includeProperties.Split 
      (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) 
     { 
      query = query.Include(includeProperty); 
     } 

     if (orderBy != null) 
     { 
      return orderBy(query).ToList(); 
     } 
     else 
     { 
      return query.ToList(); 
     } 
    } 

    public IEnumerable<TEntity> GetWithRawSql(string query, params object[] parameters) 
    { 
     return dbSet.SqlQuery(query, parameters).ToList(); 
    } 

我期待在这是否是最好的做法,查询在仪表盘上,其中一些建议计数正在被拔出开始减慢应用程序。我在想这是因为我们要为仪表板上的每个计数回退一个ilist,然后在控制器内部使用Count()方法。

我应该做以下事情吗?

  1. 将另一种方法添加到通用存储库,IEnumerable GetAll(); - 然后用这个来计算记录数。

  2. 使用方法'GetWithRawSql',然后使用SQL来计算。

  3. 还有其他的东西吗?像如下:

我会更好地移除'移位完成'计数,然后将所有不完整移位的IList带回控制器。在控制器内部,然后使用linq按状态查询并使用count()方法。即

ilist<shiftdate> allIncompleteShifts = _shiftService.GetIncompleteShifts.ToList(); 

ViewModel.InProgress = allIncompleteShifts.Where(s => s.status ==72).Count(); 
ViewModel.Submitted = allIncompleteShifts.Where(s => s.status ==73).Count(); 

这将如何影响性能

+0

您必须了解EF Query Deferred,通用资源库返回'列表()',首先您选择'select',然后您在内存中计算这些选定的项目。更好的性能将只使用'Count'像:'context.SomeEntity.Count(d => d.status == 73);' –

+0

是的,将结果放入列表会减慢执行速度,因为它必须拉回所有的结果。最好的办法是操纵你的IQueryable对象,直到你有一个可以在数据库上执行的查询。你应该使用'allIncompleteShifts.Where(s => s.status == 72).Count();'但我无法真正告诉你什么是正确的应用程序在哪里应该公开这个功能。 – Luke

+1

知识库中的关键点是什么?在没有Get方法的情况下,您可以按照完全相同的方式(甚至更好)执行Where,Include,OrderBy。 – Evk

回答

2

您有几种选择这里。一种常用的方法是从您的存储库返回IQueryable<TEntity>,而不是返回IList<TEntity>

使用这种方法,查询在数据库上执行而不是在内存中执行。这包括过滤,排序等。Count()也将被翻译成相应的SQL并在数据库上执行。

另一种方法是创建一个通用性较低的存储库,其中也包含特定的查询。

有一个讨论,你是否应该公开一个IQueryable<TEntity>in this question。结论是:这取决于您是否希望使用IQueryable<TEntity>为存储库的用户提供更大的灵活性。然后,您必须记住,用户现在可以执行您可能没有打算的查询。你可以在给定的链接中找到更多细节。

相关问题