Lamba作为参数C#MVC LINQ

时间:2017-03-14 10:34:33

标签: c# asp.net-mvc linq datatable datatables

public ActionResult Load()
        {
            string search = Request.Form.GetValues("search[value]")[0];

            var draw = Request.Form.GetValues("draw").FirstOrDefault();
            var start = Request.Form.GetValues("start").FirstOrDefault();
            var length = Request.Form.GetValues("length").FirstOrDefault();

            var sortColumn = Request.Form.GetValues("columns[" +
                Request.Form.GetValues("order[0][column]").FirstOrDefault() + "][name]").FirstOrDefault();
            var sortColumnDir = Request.Form.GetValues("order[0][dir]").FirstOrDefault();

            int pageSize = length != null ? Convert.ToInt32(length) : 0;
            int skip = start != null ? Convert.ToInt32(start) : 0;
            int totalRecords = 0;


            var v = (from a in DataContext.Company select a);

            //Search
            if (!string.IsNullOrEmpty(search) &&
            !string.IsNullOrWhiteSpace(search))
            {
                v.Where(x => x.Name == search);
            }

            //Ordinamento
            if (!(string.IsNullOrEmpty(sortColumn) && string.IsNullOrEmpty(sortColumnDir)))
                v = v.OrderBy(sortColumn + " " + sortColumnDir);

            totalRecords = v.Count();
            var data = v.Skip(skip).Take(pageSize).ToList();

            return Json(new
            {
                draw = draw,
                recordsFiltered = totalRecords,
                recordsTotal = totalRecords,
                data = data
            }, JsonRequestBehavior.AllowGet);
        }

实际上,我正在使用Jquery Datatable和服务器端模式,这种方法运行得很好,但我想用它来做法。 通过这种方式,我可以重用我的方法。 第一个问题是在“搜索”部分,因为我不知道如何动态传递数据库表(datacontext)。现在通过“var v”,但我通过表“公司”所以它是静态的(我需要将表作为参数传递。

无论如何,如果我解决它,我需要将lamba表达式作为参数传递,因为我想搜索特定的表列。

然而,我的问题的真正问题是:如何使这个函数动态化,以便我可以使用它而不重复代码?

谢谢

2 个答案:

答案 0 :(得分:0)

你传递给你的功能两个功能。 第一个Func>获取DbContext并返回选定的集合。

第二个是过滤函数,它接受一个元素并对其进行过滤。

这会改变这一行:

v.Where(x => x.Name == search);

修改

您的功能签名将如下所示:

public IEnumerable<T> Search(IQueryable<T> entites, Func<T,bool> filter)
{
// your code here
}

答案 1 :(得分:0)

我尝试为Jquery DataTable创建一个小的查询构建器。可能会有错误,但这将是一个良好的开端。这可能会对你有所帮助。

  1. 我将此useful answer用作模型绑定的参考。我不在这里编写代码,不重复它。

    使阅读请求参数的过程标准化

    public ActionResult Load(DTParameterModel dtParameters)
    {
        // do some thing
    }
    
  2. Jquery DataTable的查询构建器。

    • 搜索多列

    • 按多列排序

    • 寻呼
  3. JqueryDataTableQueryBuilder.cs

    public class JqueryDataTableQueryBuilder
    {
        private static readonly MethodInfo OrderByMethod = typeof(Queryable)
            .GetMethods().
            Single(method => method.Name == "OrderBy"
                && method.GetParameters().Length == 2);
    
        private static readonly MethodInfo OrderByDescendingMethod = typeof(Queryable)
            .GetMethods().Single(method => method.Name == "OrderByDescending"
                && method.GetParameters().Length == 2);
    
        public static IQueryable<T> BuildQuery<T>(IQueryable<T> query, DTParameterModel dtParameters)
        {
            IQueryable<T> q = query;
            //I skiped regex search
            var searchColumns = dtParameters.Columns.Where(c => c.Searchable).Select(c => c.Name).ToArray();
            if (searchColumns.Length > 0)
                if (!string.IsNullOrEmpty(dtParameters.Search.Value) && !string.IsNullOrWhiteSpace(dtParameters.Search.Value))
                {
                    int i = 0;
                    var par = Expression.Parameter(typeof(T), "x");
                    Expression exp = Expression.Constant(false);
                    //we need to bind search expressions with 'OR'
                    while (i < searchColumns.Length)
                    {
                        var expNext = GetSearchExpression<T>(searchColumns[i], dtParameters.Search.Value,par);
                        var expInvoke = Expression.Invoke(expNext, par);
                        exp = Expression.OrElse(exp, expNext.Body);
                        i++;
                    }
                    var ex = Expression.Lambda<Func<T, bool>>(exp,par);
                    q = q.Where(ex);
                }
            // order by 
            DTColumn[] columns = dtParameters.Columns.ToArray();
            foreach (var order in dtParameters.Order)
            {
                var orderColumn = columns[order.Column].Name;
                var dir = order.Dir;
                q = OrderByQuery(q, orderColumn, dir);
            }
            return q;
        }
    
        public static object GetDTResult<T>(DTParameterModel dtParameters, IQueryable<T> query,Expression<Func<T,object>> func = null)
        {
            var totalRecords = query.Count();
            query = query.Skip(dtParameters.Start).Take(dtParameters.Length);
            object data = func == null ? (object) query.ToArray() : query.Select(func).ToArray();
            var result = new
            {
                draw = dtParameters.Draw,
                recordsFiltered = totalRecords,
                recordsTotal = totalRecords,
                data = data
            };
            return result;
        }
    
        static Expression<Func<T, bool>> GetSearchExpression<T>(string propertyName, string propertyValue,ParameterExpression p)
        {
            var propertyExp = Expression.Property(p, propertyName);
            // we need to call string.Contains method
            MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
            var valueExp = Expression.Constant(propertyValue, typeof(string));
            var containsMethodExp = Expression.Call(propertyExp, method, valueExp);
            return Expression.Lambda<Func<T, bool>>(containsMethodExp, p);
        }
        static IQueryable<T> OrderByQuery<T>(IQueryable<T> source, string propertyName, string dir)
        {
            IQueryable<T> query = source;
            Type entityType = typeof(T);
            if (entityType.GetProperty(propertyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance) == null)
                throw new NullReferenceException("order by " + propertyName);
            ParameterExpression paramterExpression = Expression.Parameter(entityType);
            Expression orderByProperty = Expression.Property(paramterExpression, propertyName);
            LambdaExpression lambda = Expression.Lambda(orderByProperty, paramterExpression);
            MethodInfo genericMethod = !string.IsNullOrEmpty(dir) && !string.IsNullOrWhiteSpace(dir) && dir.ToUpper().Equals("DESC")
                ? OrderByDescendingMethod.MakeGenericMethod(entityType, orderByProperty.Type)
                : OrderByMethod.MakeGenericMethod(entityType, orderByProperty.Type);
            object ret = genericMethod.Invoke(null, new object[] { query, lambda });
            return (IQueryable<T>)ret;
        }
    }
    

    是:

    实体模型:

    public partial class Customer
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string LastName { get; set; }
        public DateTime CreatedDate { get; set; }
    }
    

    <强>标记:

     <script type="text/javascript">
        $(function () {
            $('#example').DataTable({
                "processing": true,
                "serverSide": true,
                "ajax": "/JqTableTest/Load"
            });
        });
       </script>
    
    <table id="example" class="display" cellspacing="0" width="100%">
        <thead>
            <tr>
                <th data-orderable="true" data-searchable="false" data-name="Id" data-data="Id">Id</th>
                <th data-orderable="true" data-searchable="true" data-name="Name" data-data="Name">First name</th>
                <th data-orderable="true" data-searchable="true" data-name="LastName" data-data="LastName"> Last name</th>
            </tr>
        </thead>
    </table>
    

    <强> CONTROLER:

    public ActionResult Load(DTParameterModel dtParameters)
    {
        using (Data.Entities context = new Data.Entities())
        {
            var query = context.Customer.AsQueryable();
            query = JqueryDataTableQueryBuilder.BuildQuery(query, dtParameters);
            var result = JqueryDataTableQueryBuilder.GetDTResult(dtParameters, query);
            return Json(result, JsonRequestBehavior.AllowGet);
        }
    }
    

    查询:

    -- count
    SELECT     [GroupBy1].[A1] AS [C1]
    FROM ( SELECT 
        COUNT(1) AS [A1]
        FROM [dbo].[Customer] AS [Extent1]
    )  AS [GroupBy1]
    -- result 
    SELECT TOP (10) 
    [Extent1].[Id] AS [Id], 
    [Extent1].[Name] AS [Name], 
    [Extent1].[LastName] AS [LastName], 
    [Extent1].[CreatedDate] AS [CreatedDate]
    FROM ( SELECT [Extent1].[Id] AS [Id], [Extent1].[Name] AS [Name], [Extent1].[LastName] AS [LastName], [Extent1].[CreatedDate] AS [CreatedDate], row_number() OVER (ORDER BY [Extent1].[Id] ASC) AS [row_number]
        FROM [dbo].[Customer] AS [Extent1]
    )  AS [Extent1]
    WHERE [Extent1].[row_number] > 0
    ORDER BY [Extent1].[Id] ASC
    

    您可以指定结果列

    public ActionResult Load(DTParameterModel dtParameters)
      {
        using (Data.Entities context = new Data.Entities())
        {
            var query = context.Customer.AsQueryable();
            query = JqueryDataTableQueryBuilder.BuildQuery(query, dtParameters);
            var result = JqueryDataTableQueryBuilder.GetDTResult(dtParameters, query, a => new
            {
                a.Id,
                a.Name,
                a.LastName
            });
            return Json(result, JsonRequestBehavior.AllowGet);
        }
     }
    

    查询:

    SELECT TOP (10) 
    [Extent1].[Id] AS [Id], 
    [Extent1].[Name] AS [Name], 
    [Extent1].[LastName] AS [LastName]
    FROM ( SELECT [Extent1].[Id] AS [Id], [Extent1].[Name] AS [Name], [Extent1].[LastName] AS [LastName], row_number() OVER (ORDER BY [Extent1].[Id] ASC) AS [row_number]
        FROM [dbo].[Customer] AS [Extent1]
    )  AS [Extent1]
    WHERE [Extent1].[row_number] > 0
    ORDER BY [Extent1].[Id] ASC
    

    请求搜索参数:

    draw:6
    columns[0][data]:Id
    columns[0][name]:Id
    columns[0][searchable]:false
    columns[0][orderable]:true
    columns[0][search][value]:
    columns[0][search][regex]:false
    columns[1][data]:Name
    columns[1][name]:Name
    columns[1][searchable]:true
    columns[1][orderable]:true
    columns[1][search][value]:
    columns[1][search][regex]:false
    columns[2][data]:LastName
    columns[2][name]:LastName
    columns[2][searchable]:true
    columns[2][orderable]:true
    columns[2][search][value]:
    columns[2][search][regex]:false
    order[0][column]:0
    order[0][dir]:asc
    start:0
    length:10
    search[value]:abc
    search[regex]:false
    

    查询:

    SELECT TOP (10) 
    [Filter1].[Id] AS [Id], 
    [Filter1].[Name] AS [Name], 
    [Filter1].[LastName] AS [LastName]
    FROM ( SELECT [Extent1].[Id] AS [Id], [Extent1].[Name] AS [Name], [Extent1].[LastName] AS [LastName], row_number() OVER (ORDER BY [Extent1].[Id] ASC) AS [row_number]
        FROM [dbo].[Customer] AS [Extent1]
        WHERE ([Extent1].[Name] LIKE N'%abc%') OR ([Extent1].[LastName] LIKE N'%abc%')
    )  AS [Filter1]
    WHERE [Filter1].[row_number] > 0
    ORDER BY [Filter1].[Id] ASC