gpt4 book ai didi

linq-to-entities - 如何创建一个非常动态的 LinqToEntity 查询?

转载 作者:行者123 更新时间:2023-12-01 09:38:38 24 4
gpt4 key购买 nike

我需要在不同数量的表上构建一个非常动态的 Linq 查询。例如,我有相关的表:
表_A
- 身份证
- 姓名
- 描述

表_B
- 身份证
- 表_A_ID
- 姓名
- 描述

表_C
- 身份证
- 表_B_ID
- 姓名
- 描述

我有一个字典,其中包含有关表依赖项的信息:​​
tableName、parentTableName、foreignKey、parentPK
示例:
“表_B”、“表_A”、“表_A_ID”、“ID”
“Table_C”、“Table_B”、“Table_B_ID”、“ID”

-> tableInfo["Table_B"].ForeignKey 将返回 "Table_A_ID"等。

现在用户可以选择他想查看的列。
例子:

  • Table_B.Name,Table_C.Desc
    或者
  • Table_A.Name、Table_B.Name
    或者
  • Table_A.Name、Table_B.Name、Table_B.Desc、Table_C.Name

    此选择将在另一个列表中可用:
    例如选择 3:
    viewInfo["Table_A"] 包含“名称”
    viewInfo["Table_B"] 包含 "Name", "Desc"
    viewInfo["Table_C"] 包含“名称”

    如何仅使用所需的表和字段动态创建查询以获得所需的结果?

  • 最佳答案

    我为我正在处理的项目做了同样的事情,其中​​查询是在运行时根据用户在 UI 中所做的选择完全创建的。

    我通过使用 System.Linq.Expressions 中的类来使用表达式树构造 LINQ 查询。命名空间。它非常强大,但学习曲线陡峭。

    您可以使用 LINQPad编写查询,然后转储表达式以查看树下面的样子,以便您知道如何自己构建查询。

    例如,在 LINQPad 中运行以下代码将生成表达式树的转储。

    var query = from p in Puzzles
    select p;

    query.Expression.Dump(20);

    LINQPad Screenshot

    那么如何真正编写动态创建简单 LINQ 查询的代码呢?

    考虑以下最简单的查询示例:

    var query = from person in data
    select person;

    以下代码将即时生成等效查询。

    using System;
    using System.Linq;
    using System.Linq.Expressions;
    using System.Reflection;

    namespace TestLinqGenerator
    {
    class Program
    {
    static void Main(string[] args)
    {
    // Set up dummy data
    var data = new[]
    {
    new {Name = "Fred"},
    new {Name = "Simon"}
    }.AsQueryable();
    var dataType = data.ElementType;

    // IQueryable: data
    var source = Expression.Constant(data);

    // Parameter: person
    var parameter = Expression.Parameter(dataType, "person");

    // person => person
    var lambda = Expression.Lambda(parameter, parameter);

    // Expression: data.Select(person => person)
    var callSelect = Expression.Call(GetSelect().MakeGenericMethod(dataType, dataType), source, Expression.Quote(lambda));

    // IQueryable: data.Select(person => person)
    var query = data.Provider.CreateQuery(callSelect);

    // Execute query
    var results = query.Cast<object>().ToList();

    }

    private static MethodInfo GetSelect()
    {
    // Get MethodInfo of the following method from System.Linq.Queryable:
    // public static IQueryable<TSource> Select<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate)
    return typeof(System.Linq.Queryable).GetMethods().Where(
    method => method.Name == "Select" && method.GetParameters().Length == 2 &&
    method.GetParameters()[1].ParameterType.GetGenericArguments()[0].Name == typeof(Func<,>).Name).Single();
    }

    }
    }

    您应该能够通过将其粘贴到控制台应用程序来运行此代码。使用调试器逐步了解每个步骤的作用。

    额外信息

    Queryable.Select的实现使用 Reflector 有助于理解动态编写查询时需要发生的事情。我在下面复制了它:

    public static IQueryable<TResult> Select<TSource, TResult>(this IQueryable<TSource> source, Expression<Func<TSource, int, TResult>> selector)
    {
    if (source == null)
    {
    throw Error.ArgumentNull("source");
    }
    if (selector == null)
    {
    throw Error.ArgumentNull("selector");
    }
    return source.Provider.CreateQuery<TResult>(Expression.Call(null, ((MethodInfo) MethodBase.GetCurrentMethod()).MakeGenericMethod(new Type[] { typeof(TSource), typeof(TResult) }), new Expression[] { source.Expression, Expression.Quote(selector) }));
    }

    有趣的是,Queryable.Select 的实现只需创建调用自身的 LINQ 表达式表示。 LINQ 提供程序实际上将该表达式转换为其他内容 - TSQL。 Select方法本身实际上并不执行选择。

    您的代码应该做同样的事情 - 创建 LINQ 表达式。

    一旦您对如何进行简单选择感到满意,您可以查看添加 Queryable.Where LINQ 查询的混合和其他功能。我建议保留预测(select new {x, y, z} 等),因为它们非常困难。您需要在运行时生成类型,就像编译器为您生成匿名类型一样。 System.Reflection.Emit是您完成工作的工具。

    这种方法的好处之一是您可以将它与任何 LINQ 提供程序一起使用,例如 LINQ to Entities、LINQ to SQL、Mindscape Lightspeed 和 AsQueryable 提供的内存中 LINQ 提供程序实现。 .

    我的生成 LINQ 表达式的代码将接受 IQueryable,并且在运行时它当前由 Mindscape Lightspeed IQueryables 提供,但也可以是其他之一。然后在我的单元测试中,我使用对象数组创建测试数据,然后将其转换为 IQueryable使用 AsQueryable它被传递到 LINQ 表达式生成器中。然后,我的单元测试可以生成所有范围的复杂查询,但无需数据库即可轻松测试。上面的示例显示了如何做到这一点。

    关于linq-to-entities - 如何创建一个非常动态的 LinqToEntity 查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3503180/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com