【问题标题】:A way around LINQ to Entities does not recognize the method?一种绕过 LINQ to Entities 的方法无法识别该方法?
【发布时间】:2013-06-20 22:56:23
【问题描述】:

我有一个我一直在使用的方法来对付 IEnumerable 没问题。但是我也想开始对 IQueryable 使用它。但是,我目前拥有它的方式无法正常工作,因为它试图对数据库执行我的方法。

情况如下。如果从中选择的值为 null 或属性的 Id 和名称(如果存在),我希望我选择的对象上的属性为 null。例如:

var foos = FooRepository.All().Select(s => new FooBrief()
{
    Id = s.Id,
    Customer = SimpleData.To(s.Customer, m => m.Id, m => m.Name)
});

SimpleData.To 的样子:

public class SimpleData
{
    public int Id { get; set; }
    public string Name { get; set; }

    public static SimpleData To<T>(T t, Func<T, int> id, Func<T, string> name) where T : class
    {
        if (t != null)
        {
            return new SimpleData { Id = id(t), Name = name(t) };
        }
        return null;
    }
}

有没有什么办法可以让我在允许它对数据库执行的同时获得这种行为?

注意:由于我代码中其他地方的原因,我不能使用 .ToList()。稍后我可能会添加额外的过滤器

【问题讨论】:

  • 你能用ToArray吗? :-) 以及你不能这样做的原因可能是相关的。
  • 我不能这样做的原因是我可能需要在此之后向 iqueryable 添加附加子句。所以我仍然希望它对数据库执行

标签: c# entity-framework iqueryable


【解决方案1】:

最简单的方法就是在数据库外部执行选择,使用AsEnumerable:

var foos = FooRepository.All()
                        .Select(x => new { Id = x.Id,
                                           CustomerId = x.Customer.Id,
                                           CustomerName = x.Name })
                        .AsEnumerable()
                        .Select(s => new FooBrief {
                                   Id = s.Id,
                                   Customer = new SimpleData { 
                                       Id = s.CustomerId,
                                       Name = s.CustomerName
                                   }
                                });

第一个Select只是为了确保数据库查询只拉出必填字段。如果您仍然想使用您的SimpleData.To 方法:

// Outdented to avoid scrolling
var foos = FooRepository.All()
    .Select(x => new { Id = x.Id,
                       CustomerId = x.Customer.Id,
                       CustomerName = x.Name })
    .AsEnumerable()
    .Select(s => new FooBrief {
               Id = s.Id,
               Customer = SimpleData.To(s,
                                        s => s.CustomerId,
                                        s => s.CustomerName)
            });

【讨论】:

  • 我遇到的问题,我认为我没有说清楚。是不是我可能会在此查询之后添加附加过滤(例如,一个 where 子句)。
  • @mjmcloug:那么为什么不在这一点之前添加呢?基本上,当您仍处于 EF 部分时,您无法执行自定义 .NET 方法……至少在一般情况下是这样。 (我相信有一些方法可以将简单的方法映射到存储的过程,但这对您的情况没有帮助。)您需要接受这一点并进行适当的设计。
  • 同意。问这个问题时,我假设了最坏的情况,但我很好奇是否有一种我不知道的聪明方法。恐怕现在之前不是一个选择。我得考虑一下这个
  • @mjmcloug:请注意,使用 first 表单,您可以在之后添加 Where 子句……但绝对不能添加第二个。
猜你喜欢
  • 2021-11-06
相关资源
最近更新 更多