使用SQL Server在asp.NET中查询动态

时间:2016-03-08 08:01:57

标签: json asp.net-mvc linq dynamic-linq

(如果标题不是这个问题的代表,请说明,我无法提出一个很好的简短说明)

我正在尝试为我的网络应用程序实现高级搜索功能。此搜索必须能够搜索许多可能的组合。 enter image description here

如图所示,每个组(AND或OR)可以有另一组或条件可以相等或不相等。图片应该产生一个如下所示的where子句:

WHERE (Application like '%User%' AND Host not like '%fjzhykjety%') OR (REMOTE_HOST like '%uykirlyy%' AND REMOTE_PORT not like '%55555%')

Application,Host和REMOTE_HOST是字符串,REMOTE_PORT是可以为null的int。我还有一个必须可搜索的GUID。

目前这个前端搜索是以角度编写的,并且让我跟随json(json取决于嵌套的组和条件)示例:

{
    "group": {
        "operator": "OR",
        "rules": [
            {
                "group": {
                    "operator": "AND",
                    "rules": [
                        {
                            "condition": "=",
                            "field": {
                                "name": "Application",
                                "type": "select"
                            },
                            "data": "User"
                        },
                        {
                            "condition": "<>",
                            "field": {
                                "name": "Host",
                                "type": "text"
                            },
                            "data": "fjzhykjety"
                        }
                    ]
                }
            },
            {
                "group": {
                    "operator": "AND",
                    "rules": [
                        {
                            "condition": "=",
                            "field": {
                                "name": "REMOTE_HOST",
                                "type": "text"
                            },
                            "data": "uykirlyy"
                        },
                        {
                            "condition": "<>",
                            "field": {
                                "name": "REMOTE_PORT",
                                "type": "number"
                            },
                            "data": 55555
                        }
                    ]
                }
            }
        ]
    }
}

我需要一种方法将此数据发送到我的.NET应用程序(使用REST API)并在数据库中进行查询。我查看了动态linq来进行查询,但由于json文件的格式总是相同的,因此很难在C#中创建一个类,并为此搜索构建动态linq查询。 / p>

实施此高级搜索的最佳方法是什么?

1 个答案:

答案 0 :(得分:1)

以下是动态查询的示例。此外,您可以与您的查询结合使用linqkit是一个很好的谓词构建器。

http://www.albahari.com/nutshell/linqkit.aspx https://github.com/scottksmith95/LINQKit

public List<CustomerPointsDetail> GetCustomerPointsDetails(
            int customerId,
            int? catalogRewardId = null,
            long? couponId = null,
            long? transactionId = null,
            CustomerPointsDetailStatus? inStatus = null,
            CustomerPointsDetailStatus? notInStatus = null,
            bool? isPointsGreaterThanZero = null,
            bool? isRemainingPointsGreaterThanZero = null,
            CustomerPointsDetailOperationType? operationType = null,
            DateTime? startDate = null,
            DateTime? endDate = null,
            bool isExpiredRecordsIncluded = false)
        {
            var query = this.customerPointsDetailRepository.Table.Where(cpd => cpd.CustomerId == customerId);

            if (catalogRewardId.HasValue)
            {
                query = query.Where(cpd => cpd.CatalogRewardId == catalogRewardId);
            }

            if (couponId.HasValue)
            {
                query = query.Where(cpd => cpd.CouponId == couponId);
            }

            if (transactionId.HasValue)
            {
                query = query.Where(cpd => cpd.TransactionId == transactionId);
            }

            if (inStatus.HasValue)
            {
                query = query.Where(cpd => cpd.Status == inStatus);
            }

            if (notInStatus.HasValue)
            {
                query = query.Where(cpd => cpd.Status != notInStatus);
            }

            if (isRemainingPointsGreaterThanZero.HasValue)
            {
                if (isRemainingPointsGreaterThanZero.GetValueOrDefault())
                {
                    query = query.Where(cpd => cpd.RemainingPoints.HasValue && cpd.RemainingPoints > 0);
                }
                else
                {
                    query = query.Where(cpd => cpd.RemainingPoints.HasValue && cpd.RemainingPoints < 0);
                }
            }

            if (isPointsGreaterThanZero.HasValue)
            {
                if (isPointsGreaterThanZero.GetValueOrDefault())
                {
                    query = query.Where(cpd => cpd.Points > 0);
                }
                else
                {
                    query = query.Where(cpd => cpd.Points < 0);
                }
            }

            if (operationType.HasValue)
            {
                query = query.Where(cpd => cpd.OperationType == operationType);
            }

            if (!isExpiredRecordsIncluded)
            {
                query = query.Where(cpd => !cpd.PointsExpireDate.HasValue
                                           || (cpd.PointsExpireDate.HasValue && cpd.PointsExpireDate > DateTime.Now));
            }

            if (startDate.HasValue)
            {
                query = query.Where(cpd => cpd.CreateDate >= startDate);
            }

            if (endDate.HasValue)
            {
                query = query.Where(cpd => cpd.CreateDate <= endDate);
            }

            query = query.OrderBy(cpd => cpd.PointsExpireDate);

            return query.ToList();
        }

Linqkit示例

IQueryable<Product> SearchProducts (params string[] keywords)
{
  var predicate = PredicateBuilder.False<Product>();

  foreach (string keyword in keywords)
  {
    string temp = keyword;
    predicate = predicate.Or (p => p.Description.Contains (temp));
  }

  return dataContext.Products.Where (predicate);
}

编辑

你需要一个表达式给你的方法和。您可以与Linqkit结合使用。

    Expression<Func<Product, bool>> e1 = DynamicExpression.ParseLambda<Product, bool>("Type= \"Type_A\"");    

    OR 

Expression<Func<Product, bool>> e1 =  p => p.Type="Type_A";

在程序中调用SearchProduct之前

var expressions = new Dictionary<Expression<Func<Product, bool>>, bool>();

Expression<Func<Product, bool>> e1 =  p => p.Type="Type_A";
Expression<Func<Product, bool>> e2 =  p => p.Type="Type_B";

expressions.Add(e1,true);
expressions.Add(e2,true);

SearchProducts(expressions); //send expression list for evoluate

    IQueryable<Product> SearchProducts (Dictionary<Expression<Func<Product, bool>>, bool>  expressionList)
    {
      var predicate = PredicateBuilder.False<Product>();

      foreach(expression in expressionList)
      {

           if(expression.Value) // AND
           {
               predicate = predicate.And(expression.Key);
           }else   // OR
           {
               predicate = predicate.Or(expression.Key);
           }

       }
       .
       .
  }