迭代 Linq 表达式并将其转换为 DB 参数

发布于 2024-10-07 23:58:54 字数 578 浏览 2 评论 0原文

我如何迭代 Linq 表达式并将其转换为数据库参数,以便避免将多个参数作为输入传递给 DAL 方法

业务层: 在BL中,我有这样的代码

  database.GetProduct(a => a.ProductType == "tea" || a.Price <= 5);

在DAL中,我使用普通的ADO.Net,并希望将从BL返回的表达式转换为ADO.Net参数

数据访问层:

 public DataSet GetProduct(Expression<Func<Product, bool>> pred)
 {

    step 1:
          Iterate the predicate and create new sqlparameter.
    step 2:
      return database.ExecuteDataset(parameters)    
 }

如何迭代“pred”& ;将其转换为 SQLParameter

How i can iterate a Linq Expression and convert it into DB parameter so that i can avoid passing multiple parameter as input to the DAL method

Business Layer:
In BL i have code like this

  database.GetProduct(a => a.ProductType == "tea" || a.Price <= 5);

In DAL i use plain ADO.Net and want to convert the expression whatever i returned from BL to ADO.Net parameters

Data Access Layer:

 public DataSet GetProduct(Expression<Func<Product, bool>> pred)
 {

    step 1:
          Iterate the predicate and create new sqlparameter.
    step 2:
      return database.ExecuteDataset(parameters)    
 }

How i can iterate "pred" & convert it to SQLParameter

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

紅太極 2024-10-14 23:58:54

正如马修所写,您需要处理表达式树。这可以使用 ExpressionVisitor 来完成,它允许您为表达式树中的每种类型的节点编写一些代码。但是,如果您只想支持简单的表达式(例如示例中的表达式),那么您可以使用 NodeType 属性来处理它。

结构可能类似于:

static void HandlePrimitive(Expression e) {
  // TODO: Handle primitive cases (>, <, <=, !=, >=, ..)
  Console.WriteLine(e.NodeType);
}

static void Process(Expression e) {
  if (e.NodeType == ExpressionType.OrElse)
  {
    // Process left subexpression (one (in)equality) as primitive
    // and right subexpression recursively (it may be either primitive 
    // or another OrElse node.
    var be = e as BinaryExpression;
    HandlePrimitive(be.Left);
    Process(be.Right);
  }
  else HandlePrimitive(e);
}

Expression<Func<Product,bool>> f = a => a.ProductType == "tea" || a.Price <= 5;
Process(f.Body);

Process 方法递归地迭代使用“or”运算符组成的所有子表达式(您可以类似地支持“and”)。 HandlePrimitive 方法将处理可以使用 || 组成的表达式。这些是其他BinaryExpression值(例如EqualLessThanEqual)。您需要查看它们的LeftRight` 属性来找出要比较的属性名称和值。但对于这个简单的工作来说,这应该不会是太多工作表达式的类型。

As Matthew writes, you'll need process the expression tree. This can be done using ExpressionVisitor, which allows you to write some code for every type of node in the expression tree. However, if you want to support only simple expressions (such as the one in your example), then you could use NodeType property to process it.

The structure could be something like:

static void HandlePrimitive(Expression e) {
  // TODO: Handle primitive cases (>, <, <=, !=, >=, ..)
  Console.WriteLine(e.NodeType);
}

static void Process(Expression e) {
  if (e.NodeType == ExpressionType.OrElse)
  {
    // Process left subexpression (one (in)equality) as primitive
    // and right subexpression recursively (it may be either primitive 
    // or another OrElse node.
    var be = e as BinaryExpression;
    HandlePrimitive(be.Left);
    Process(be.Right);
  }
  else HandlePrimitive(e);
}

Expression<Func<Product,bool>> f = a => a.ProductType == "tea" || a.Price <= 5;
Process(f.Body);

The Process method recursively iterates over all the subexpressions composed using the "or" operator (you could support "and" similarly). The HandlePrimitive method would deal with expressions that may be composed using ||'s. These are otherBinaryExpressionvalues (e.g.EqualorLessThanEqual). You'll need to look at theirLeftandRight` property to find out the property name and value to be compared against.. but it shouldn't be too much work for this simple type of expressions.

烟花易冷人易散 2024-10-14 23:58:54

您需要研究在表达式上使用访问者模式,以便可以遍历生成的表达式树以确定将哪些成员投影为参数。 IQToolkit 项目有一个很好的 ExpressionVisitor 基类,您可能会发现它可以用作基类访客模式的实现。您可以将其子类化以专门处理 VisitMemberAccess 来处理您的属性。

You need to look into using the visitor pattern on your expression so you can walk through the expression tree you generate to determine which members to project as parameters. The IQToolkit project has a nice ExpressionVisitor base class that you could find useful as a base implemenation of the visitor pattern. You could subclass that to handle the VisitMemberAccess specifically to deal with your properties.

稀香 2024-10-14 23:58:54

你不想走这条路。您将重新实现 LINQ to SQL。我可能建议您使用可选参数:

public DataSet GetProduct(int? maxPrice = null, string type = null)
{
    //... snip ...
    if (price.HasValue) whereClause += " OR price <= " + maxPrice";
    //... snip ...
}

You do not want to go down this road. You are going to be reimplementing LINQ to SQL. I might suggest that you use optional arguments:

public DataSet GetProduct(int? maxPrice = null, string type = null)
{
    //... snip ...
    if (price.HasValue) whereClause += " OR price <= " + maxPrice";
    //... snip ...
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文