【问题标题】:How can I call local method in Linq to Entities query?如何在 Linq to Entities 查询中调用本地方法?
【发布时间】:2013-09-10 09:08:56
【问题描述】:

我有以下代码:

public void SalesCount(string customerId)
{
  ..
  ..
  return ...;
}

var resultQuery = dataContext.Customers
.Where (c => c.Name == "Alugili")
.Where (c => SalesCount(c.CustomerId) < 100);

当我执行 resultQuery 时,我得到一个 SQL 异常的翻译。

我需要在 Where 中调用 SalesCount 我可以这样做,是否有任何解决此问题的方法!

【问题讨论】:

  • 标头中的 Linq2SQL,标签中的 EF。真相在哪里? :)
  • Linq2SQL 和 EF 是相似但完全不同的技术。我想,你在某个地方感到困惑。
  • 当面对这样的情况时,你会问自己:是否有可能实现 SalesCount 在 T-SQL 中所做的任何事情?如果是这样,请尝试创建一个代表Customers 表的视图,但添加一个额外的列(SalesCount 的结果)。然后将 LINQ 中的 VIEW 映射到 SQL 实体,并对该实体执行选择。通过这种方式,您可以避免在 .NET 中处理大量记录,而让 RDBMS 为您完成。
  • 非常,您可以制作 CLR UDF 并在您的 linq 中调用它。在下面提到的情况下,如果使用 ToArray、AsEnumerable 等,您将获得内存负载。

标签: c# .net linq entity-framework


【解决方案1】:

只是你不能。不能直接在SQL服务器上执行C#代码,只能使用Expressions和一些特殊的识别函数...

除非您在 LINQ-to-Objects 中转换您的查询(至少部分)...

var resultQuery = dataContext.Customers
    .Where (c => c.Name == "Alugili")
    .AsEnumerable()
    .Where (c => SalesCount(c.CustomerId) < 100);

请注意,最后一个Where 将在客户端执行,因此将从数据库中获取许多无用的行。

【讨论】:

  • +1 用于使用AsEnumerable() 这可以防止在扩展“内存查询”时不必要地加载内存。
  • ToList 和 ToArray 直接加载数据,但 AsEnumerable 没有我会测试它并给你反馈非常感谢!
  • 在这种情况下,ToListToArrayAsEnumerable 在内存加载方面类似。关键字是materialized query
  • @HamletHakobyan 你有任何链接或任何有用的信息吗?
  • 对于实体加载到内存中的问题,我认为这是最合理的解决方案,EF暂时不支持此功能,我将使用它,我有时间可以扩展动态库我将发布扩展名。非常感谢!
【解决方案2】:

试试

var resultQuery = dataContext.Customers
.Where (c => c.Name == "Alugili")
.ToArray()
.Where (c => SalesCount(c.CustomerId) < 100);

但是第二个 Where 不是作为 SQL 运行,而是在本地运行 - 所有名为“Alugili”的客户都从数据库中提取...

否则你必须直接在 where 方法中写出你的方法作为 lambda 表达式。

【讨论】:

  • 它正在工作,非常感谢你能告诉我,ToArray 将从数据库中加载所有实体吗?我有一个延迟加载我不需要全部加载这可能吗?
  • 看看这个:damieng.com/blog/2009/06/24/…。也许这可以解决您的问题。
  • 你必须明白@xanatos 做了同样的事情。它也在工作。不,它会加载在c =&gt; c.Name = "Alugili".. 中幸存的所有实体。在更广泛的情况下,危险的许多记录,但可能不是全部......
【解决方案3】:

在两个where条件之间添加&&..它会起作用

【讨论】:

    【解决方案4】:

    是的,你可以。

    但您应该更改函数的返回类型:

    public **int** SalesCount(string customerId)
    {
      ..
      ..
      return 500;
    }
    
    
    var resultQuery = dataContext.Customers.AsEnumerable()
                     .Where (c => c.Name == "Alugili" && SalesCount(c.CustomerId) < 100);
    

    【讨论】:

    • 不,你不能。 RDBMS 是实际执行查询的那个。在这种情况下,LINQ 代码只是一个编排器,基于该编排器编写 SQL 查询、发送到数据库并在那里执行。如果是真的,那么在随机 LINQ 查询上执行 .Count() 将导致整个表通过 TCP 连接传输到 .NET 中,并且每一行检查用户程序员想到的任何条件,只是为了计算一个伯爵。
    • @EduardDumitru 我的代码只是将 linq2sql 转换为 linq2Object
    • 如果您注意提问的用户所写的内容,您会注意到代码行var resultQuery = dataContext.Customers。假设他没有故意以任何方式欺骗我们,他很可能使用 LINQ to SQL,而且人们也可以假设他正在使用 SQL Server 完成所有这些工作。照你说的做是非常昂贵的。所有 可以 由 DB 执行的 where 子句都应该放在对 .AsEnumerable() 的调用之前。此外:答案是不,不,你不能,但你可以将所有东西都带入 .NET,并导致大量资源消耗
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多