2013-11-28 80 views
1

我正在與具有性能問題的SQL Server上的實體框架的項目ASP.NET MVC3。實體框架 - 查詢執行性能問題

每次使用EF和Linq從視圖/表中加載數據。我可以通過SQL Server Profiler看到所有的表/視圖內容都被檢索到,因爲where條件不會出現在profiler中。我認爲只有後來被LINQ過濾了。

它是正確的嗎?如何只加載我首先需要在SQL Server上的數據?

這是我的示例代碼:

var query = unitWork.City.GetFirstorDefault(item => item.City == cityCode); 

下面我們數據層與數據呼叫例如提取。感謝您的答覆。

public class UnitOfWork : IUnitOfWork, IDisposable 
    { 

     #region CONSTRUCTOR 
     public UnitOfWork() 
     { 
      _context = new MyApplicationEntities(); //DataContext 
      _context.ContextOptions.LazyLoadingEnabled = true; 
      _context.ContextOptions.UseLegacyPreserveChangesBehavior = false; 
     } 
     #endregion 

     // DESC_RECHARGEABLE is a table in DB   
     public IGenericRepository<DESC_RECHARGEABLE> RepRechargeable 
     { 
      get{return _repRechargeable ?? (_repRechargeable = new GenericRepository<DESC_RECHARGEABLE>(_context));} 
     } 



} 

    public interface IGenericRepository<T> : ICollection<T> 
     where T : class 
    { 
     IEnumerable<T> Query(Func<T, bool> predicate); 

void Update(T entity); 

T GetFirstorDefault(Func<T, bool> predicate); 

IEnumerable<T> GetAll(); 

T GetByKey(Func<T, bool> predicate); 

bool Remove(T entity); 

void Add(T entity); 

     ObjectSet<T> GetQuery(); 
    } 


public class GenericRepository<T> : IGenericRepository<T> 
     where T : class 
    { 
     private MyApplicationEntities Currentcontext; 
     public ObjectSet<T> entitySet; 
     private List<GenericRepository<T>> _list = null; 
     private string entityName; 

     public GenericRepository(MyApplicationEntities context) 
     { 
      if (context == null) 
       throw new ArgumentNullException("context"); 
      this.Currentcontext = context; 
      this.entitySet = context.CreateObjectSet<T>(); 
      this.entityName = entitySet.Name; 
     } 

     #region READ 
     public IEnumerable<T> Query(Func<T, bool> predicate) 
     { 
      return this.entitySet.Where(predicate); 
     } 


     public T GetFirstorDefault(Func<T, bool> predicate) 
     { 
      return this.Query(predicate).FirstOrDefault(); 
     } 


     public IEnumerable<T> GetAll() 
     { 
      return this.entitySet.AsEnumerable(); 
     } 

     public T GetByKey(Func<T, bool> predicate) 
     { 
      return this.Query(predicate).FirstOrDefault(); 
     } 
     #endregion 
} 

//這裏客戶端調用示例,加載所有DESC_RECHARGEABLE行的條件

var tempList = _unitofWork.RepRechargeable.Query(item => item.COMPANY_CODE == companyCode 
                  && item.DIVISION_CODE == divisionCode && !string.IsNullOrEmpty(item.PROPERTY)); 
+1

你應該告訴我們你的Linq代碼 –

+1

告訴我們代碼 –

+0

顯示'unitWork.City'和'GetFirstorDefault'方法的執行情況 – Moho

回答

0

最有可能您的unitOfWork.City.GetFirstOrDefault方法的實現應用過濾器的DbSet<T>之前枚舉。如果您展示更多代碼,我們可以確定發生的情況。

3

好吧,根據我在OP中的評論,我會在這裏堅持我的脖子。

使用Func<T, bool> predicate很可能是您的問題的根源。當您使用Func<>時,您的代碼在本地內存中針對目標結構(在您的情況下爲query變量)被執行。

通過微妙地改變方法簽名使用Expression<Func<T, bool>> predicate,你將減輕這個問題,並允許延期執行(即在SQL服務器等處理)。

這是因爲(Expression<Func<>>)在進行查詢之前創建了表達式樹,並將此(IQueryable)發送到服務器。這然後返回過濾列表。相比之下,當使用Func<>時,請求整個對象圖並在本地存儲器中進行後處理。

我不是這方面的專家,但是這應該可以幫助你找到一個解決方案。

快速比較發現:

  • 爲IEnumerable的擴展方法與Func<T>;
  • 的擴展IQueryable的方法與操作操作Expression<Func<T>>;

這意味着你將只能得到遞延IQueryable通過使用Expression<Func<T>>。四捨五入,這裏就是你的問題的方法現在看起來像:

接口:

T GetFirstorDefault(Expression<Func<T, bool>> predicate); 

實現:

public T GetFirstorDefault(Expression<Func<T, bool>> predicate) 
{ 
    return this.Query(predicate).FirstOrDefault(); 
} 

顯然,所有其他方法將跟隨這種變化,它應該獲得成功。

讓我知道這是如何爲你解決的。

[編輯] - 增添了些許鏈接(沒有雙關語意),讓兩者之間的差異概括: