【问题标题】:LINQ with anonymous class/properties具有匿名类/属性的 LINQ
【发布时间】:2011-10-14 11:23:21
【问题描述】:

我正在将一个项目从使用标准 DB 查询转移到使用 EF 和 LINQ。我有一个包含某些记录的表,我将使用这些记录来构建如下所示的查询:

select * from client where city = ?

在我的原始表中,我将从表中提取客户端和城市来构建该查询。

上面的客户和城市也可能是另一个表和/或字段。我将如何使用 EF 和 LINQ 做同样的事情?这甚至可能吗,还是我必须构建一个单独的类来处理所有这些逻辑?

var query = from c in context.clients
            where c.city == ?
            select c;

编辑:这与加入查询无关。它是关于构建动态查询的。我不知道当我运行程序时是否会查询城市、地址,甚至是“客户”表本身。它可能在另一张桌子上。我希望能够动态构建查询。

【问题讨论】:

  • 我认为我们需要更多信息。让我们看看表定义。
  • 请澄清。我无法按照您的要求进行操作

标签: c# linq entity-framework


【解决方案1】:

如果您的表通过外键连接,您可以使用 LINQ 访问另一个表中的值,如下所示。 (我通过假设有一个“地址”表并且客户表有一个外键来扩展您的示例。)

var query = from c in context.clients
            where c.address.city == ?
            select c;

编辑:(试图理解您的原始问题和后续评论...)

认为你要问的是你是否可以做这样的事情?

string cityName = "Los Angeles"; // Could be a parameter, etc.

var query = from c in context.clients
            where c.city == cityName
            select c;

或者,从你的问题更进一步,可能是这样的:

string cityName = (from c in context.cities
                   where c.id == 5
                   select c.name).FirstOrDefault();

var query = from c in context.clients
            where c.city == cityName
            select c;

由于它是一个 IQueryable,因此您还可以动态添加更多条件。

if (someCondition)
{
    query = from q in query
            where q.someField >= conditionValue
            select q;
}

或其他。在实际需要结果之前,不会实际评估/执行查询表达式树。

【讨论】:

  • 我一定不是很清楚。我有原始查询,它曾经是客户和城市是表提供的字符串值,我正在动态构建查询。我希望能够在 EF 中使用 LINQ 做同样的事情,并动态构建 LINQ 查询。这可能吗?
  • 是的,你并不清楚。因此,为了重申您的问题,从您的原始查询中,您想知道是否可以在运行时提供?
  • 如果这不是您要问的,也许您可​​以编辑您的问题以提供更多详细信息?
【解决方案2】:

你可以像这样编写 GalacticCowboy 提出的查询

var query = from c in context.clients
        join add in context.Addresses on c.AddressID equals add.AddressID
        where addr.city == ?
        select c;

这两个查询都会生成内部连接,性能没有差异。唯一的区别是如果地址对于客户端是可选的,那么c.address.City 将在没有地址的客户端上抛出异常,而此查询将返回一个空枚举

【讨论】:

    【解决方案3】:

    如果您真的想在运行时构建查询,那么有几个基于 linq 的解决方案可用 - 您可以在运行时将代码编译成临时程序集,或者您可以使用 MS 示例之一中的 DynamicLinq。

    有关更多信息,请参阅以下问题和答案:How to create LINQ Query from string?

    【讨论】:

      【解决方案4】:

      我认为您可以采取一些方法。

      首先,您可以查看Dynamic LINQ library(还可以查看 David Fowler 对其的更新here)。使用这种方法,您可以像这样编写 LINQ 查询:

      var results = Context.Clients
                      .Where("city=='Los Angeles'")
                      .OrderBy("address");
      

      因此,您的 WhereOrderBy 谓词是在后台转换为表达式的字符串。

      其次,如果您知道要查询的内容但不确定是否要查询一个或多个字段,则可以使用像 PredicateBuilder 这样的库,如下所示:

      var predicate = PredicateBuilder.True<Clients>();
      foreach(var criteria in searchCriteria) {
        if (criteria.Key=="city"){
          predicate = predicate.And(c => c.city==criteria.Value);
        } else if (criteria.Key=="address"){
          predicate = predicate.And(c => c.address==criteria.Value);
        }
      }
      var results = Context.Clients.Where(predicate);
      

      第三,可能也是最困难的,是构建自己的表达式树。这肯定需要最多的代码(一开始有点深),但它非常非常强大。这个来自 MSDN 的 example 很好地介绍了您可以做什么(并且可能比我在这里做的更简洁)。

      所以,基本上,您有几个选择。动态 LINQ 库似乎是最容易使用的,但我从未使用过它,所以我不能确定它的工作情况和可靠性。如果有帮助,还有一个用于动态 LINQ 库的 NuGet 包。

      祝你好运。希望这会有所帮助!

      【讨论】:

      • 所有这些都适用于 LINQ to SQL,但 EF 已经拥有允许在不需要谓词构建器的情况下传递字符串的对象服务方法。它实际上并没有转化为表达式树,而是转化为规范的查询表达式。
      【解决方案5】:

      如果您想在 Entity Framework 中构建动态查询,您可以尝试动态构建表达式树。但是,实体框架为您提供了一些额外的选项。

      首先,EntityObject 有一些额外的对象服务方法,它们已经让您构建一个字符串并将其直接传递给许多谓词,包括 Where:

      c.Customers.Where("City = 'London'");
      

      如果您需要构建更大的查询,包括动态设置查询源,请考虑使用 EntitySQL。例如,使用 EntitySQL,您可以使用简单的字符串解析并生成如下代码:

      string entitySQL = "SELECT VALUE c FROM Customers AS c WHERE c.Address.City = 'Seattle';";
      ObjectQuery<Customer> query = context.CreateQuery<Customer>(entitySQL);
      

      您可以在Entity Framework Query Samples 中看到这两个选项的实际效果。

      【讨论】:

      • 这与我在这里寻找的内容一致,谢谢。有了这个,如果我在设计时不知道“客户”是什么,我将如何在运行时进行转换? (因为它可能是“客户”、“订单”等)
      • 如果您在运行时动态设置结果源或投影列,则需要使用 context.CreateQuery。这是 EF 示例中的示例: string entitySQL = "SELECT Min(p.UnitPrice) AS MinPrice, p.Category.CategoryName FROM Products AS p GROUP BY p.Category.CategoryName;"; ObjectQuery 查询 = context.CreateQuery(entitySQL);
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-07
      • 1970-01-01
      相关资源
      最近更新 更多