2015-11-27 118 views
1

其實我正在與Linq和UOW(工作單元)合作,並且我正在用linq輕鬆訪問bbdd。我知道,如果我要得到一個表格的第一行,我可以這樣做:選擇top1與Linq

int test4 = (from p 
      in uow.ProductR.context.product 
      where p.Id == 1715 select p.Id).FirstOrDefault(); 

這將在SQL Server中執行此:

SELECT TOP (1) 
    [Extent1].[Id] AS [Id] 
    FROM [dbo].[product] AS [Extent1] 
    WHERE 1715 = [Extent1].[Id] 

我的問題是,我可以做與LINQ一樣反對我的UOW的通用儲存庫?我的意思是,當我執行

int test2 = uow.ProductR.Get(p => p.Id == 1715).Select(p => p.Id).FirstOrDefault(); 

或者

var test3 = uow.ProductR.Get(p => p.Id == 1715).Select(p => new { p.Id }); 

在SQL Server中,我得到:

SELECT 
[Extent1].[Id] AS [Id], 
[Extent1].[Name] AS [Name], 
FROM [dbo].[product] AS [Extent1] 
WHERE 1715 = [Extent1].[Id] 

當然,用第二種方式,當數據庫有50萬行,它會很慢。 (我有更多的列,不僅2)

編輯:這裏是用GET聲明

public class GenericRepository<TEntity> : IGenericRepository<TEntity> where TEntity : class 
{ 

    internal contextEntities context; 
    internal DbSet<TEntity> dbSet; 

    public GenericRepository(contextEntities context) 
    { 
     this.context = context; 
     this.dbSet = context.Set<TEntity>(); 
    } 

    public virtual IEnumerable<TEntity> Get(
     Expression<Func<TEntity, bool>> filter = null, 
     Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, 
     string includeProperties = "") 
    { 
     IQueryable<TEntity> query = this.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).AsQueryable(); 
     } 
     else 
     { 
      return query.AsQueryable(); 
     } 
    } 
} 

我希望我已經很好地解釋了類。

+3

「Get」方法是如何實現的?這個聲明'uow.ProductR.Get(p => p.Id == 1715).Select(p => p.Id).FirstOrDefault();'應該使用'SELECT TOP 1' – Habib

回答

5

Get需要返回IQueryable,而不是像現在這樣返回IEnumerable。然後,Get的參數也變得無用,因爲調用者可以做Get().Where(...)。 API表面變得更清潔,因爲您可以刪除參數。

但是你失去了以何種方式查詢數據庫的控制。我假設你正在爲測試目的而創建一個存儲庫(如果不是這樣做可能是一個不錯的選擇)。測試以這種方式執行的查詢變得更加困難。

+0

這就是問題所在。我沒有看到那該死的IEnumerable。 上面的代碼是測試,但目前我有幾個項目的UOW模式正確實施,並且這些項目運行良好,同時有50到400人在線的項目。 (5層,前,後,應用程序,達爾項目...) 我不明白你爲什麼說這可能不是一個正確的選擇。我需要閱讀並通知我一些事情? 謝謝 –

+0

我可以更好地回答更多的信息。爲什麼添加一個存儲庫(而不是直接使用EF)? – usr

+0

我有由UOW管理的EF。所以當我需要前端的數據時,我可以訪問Dal,在那裏我會對UOW進行LINQ查詢。 這將是我現在的過程的簡化示例。 –

0

返回IQueryable將爲您提供更大的靈活性,但它也暴露了隨機修改您在存儲庫中定義的查詢的可能性。如果您想爲使用您的存儲庫返回前N行的人提供標準機制,則可以添加一些其他可選屬性(請注意,如果您希望允許通過您的頁面進行分頁,則與Skip一起使用是一種有用的機制存儲庫而不創建單獨的機制或公開底層的IQueryable)。

你可以在你的Get方法的簽名更改爲類似這樣:

public virtual IEnumerable<TEntity> Get(
    Expression<Func<TEntity, bool>> filter = null, 
    Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, 
    string includeProperties = "", int? maxResults = null) 
在Get方法

然後(這需要重構,但你的想法):

if (orderBy != null) 
    { 
     return maxResults.HasValue() ? orderBy(query).Take((int)maxResults).ToList() : orderBy(query).ToList(); 
    } 
    else 
    { 
     return maxResults.HasValue() ? query.take((int)maxResults).ToList() : query.ToList(); 
    } 

注意您調用AsQueryable()不應該是必需的,因爲IOrderedQueryable和IQueryable都實現了IEnumerable。相反,調用ToList()以實現結果集,以便執行。

+0

是的,我明白你的意思我,但我的主要問題是,不僅獲得1行,如果不是,那就是在數據庫執行查詢不完全是我想在LINQ運行(所以它是效率低下)。它回覆了比想要更多的列 謝謝 –