2015-11-27 120 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运行(所以它是效率低下)。它回复了比想要更多的列 谢谢 –