我的通用存储库中具有以下功能。我在var list = query.ToPagedList(pageNumber, pageSizeNumber);行有两个问题

public IEnumerable<T> GetPagedListDbContext(string searchFieldName, string searchText, string searchOperator, string sortFieldName, int? page, int? pageSize)
    {
        int pageSizeNumber = (pageSize ?? 20);
        int pageNumber = (page ?? 1);
        string sql = string.Empty;

        sql = string.Format("Select * From {0} q ", typeof(T).Name);
        switch (searchOperator)
        {
            case "Starts With":
                sql += string.Format("Where q.{0} like '{1}%' ", searchFieldName, searchText);
                break;
            case "Ends With":
                sql += string.Format("Where q.{0} like '%{1}' ", searchFieldName, searchText);
                break;
            case "Contains":
                sql += string.Format("Where q.{0} like '%{1}%' ", searchFieldName, searchText);
                break;
            case "Equal To":
                sql += string.Format("Where q.{0} == '{1}' ", searchFieldName, searchText);
                break;
            case "Not Equal To":
                sql += string.Format("Where q.{0} != '{1}' ", searchFieldName, searchText);
                break;
        }

            if (sortFieldName == null)
            {
                sql += "Order By q.Id ";
            }
            else
            {
                sql += string.Format("Order By q.{0} ", sortFieldName);
            }

            // RepoDbSet is DbSet
            DbSqlQuery<T> query = RepoDbSet.SqlQuery(sql);
            var list = query.ToPagedList(pageNumber, pageSizeNumber);

            return list;
        }



它返回表中的所有记录。 (下面的Sql跟踪)
它执行两次相同的查询。

SQL跟踪
事件类文本数据

RPC:完整的exec sp_reset_connection

SQL:BatchCompleted Select * From Book q按q.Id排序

RPC:完整的exec sp_reset_connection

SQL:BatchCompleted Select * From Book q按q.Id排序

跟踪停止


问题:
为什么不使用SkipTake(例如OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY)执行查询?

为什么要执行两次?

当我检查最后一行return list时,它的总数为20,而不是表中的总行数,并且不会再次命中数据库。如何查询?

是否可以使用Linq执行相同的过程?

最佳答案

在后台,ToPagedList将执行两项操作:

要获取记录总数(用于知道将有多少页):

query.Count()


要获取当前记录页面:

query.Skip((pageNumber - 1) * pageSize).Take(pageSize)


这些将导致您看到两个查询。

它将运行您的自定义串联SQL,创建对象的内存中集合,然后对集合中的对象执行LINQ。

这是了解LINQ的重要要点。如果该集合支持IQueryable,则该集合将传递一个表达式树,它可以仔细转换为适当的SQL。

如果仅支持IEnumerable,则对内存中的对象集合进行查询。

显然,DbSqlQuery没有实现IQueryable。

而不是连接SQL,您应该公开基础表对象(EntityFramework?Linq2Sql?什么ORM?)并在该对象上运行查询:

var books = context.Books; //or whatever

var query = books.Where(b => b.Name == "Something");

// You can build up a query by chaining more operataions
// on to it
query = query.Where(b => b.PublishDate < DateTime.Today);

query = query.OrderBy(b => b.Id);

// Your ORM may be able to handle the StartsWith, EndsWith,
// Contains string methods. Check its documentation.
query = query.Where(b => b.Name.StartsWith("The"))

// Since the query object implements IQueryable, it can translate into
// two appropriate SQL queries.
return query.ToPagedList(2, 50);


相关:Returning IEnumerable<T> vs. IQueryable<T>

10-07 16:05
查看更多