【问题标题】:Using extension method in Linq to Entities在 Linq to Entity 中使用扩展方法
【发布时间】:2017-10-26 16:52:41
【问题描述】:

代码:

public static IEnumerable<TableRowModel> GetRows()
        {
            var to_ret = db.TableRows.select(x=> new TableRowModel(){
                TableRowId = x.TableRowId,
                Type = x.Type,
                Name = x.Name,
                CreatedAt = x.CreatedAt,
                ModifiedAt = x.ModifiedAt,
                Enums = x.Enums.Select(y => y.ToEnumModel()),
            });
            return to_ret;
        }

public static EnumModel ToEnumModel(this Enum x)
        {
            var to_ret = new EnumModel()
            {
                CFPId = x.CFPId,
                CreatedAt = x.CreatedAt,
                ModifiedAt = x.ModifiedAt,
            };
            return to_ret;
        }

使用GetRows 方法时出现以下错误:

LINQ to Entities 无法识别该方法

鉴于该错误,据了解LINQ To Entities 无法识别扩展方法ToEnumModel。 我想知道是否有办法解决这个问题? 这样我就不会在GetRows 扩展中再次重复ToEnumModel 代码。

【问题讨论】:

  • 您可以在查询中将AsEnumerable 放在Select 之前,这样它将运行SQL,然后在内存中进行映射。此外,您可能想查看可以为您执行此操作的库,例如 AutoMapper。
  • @juharr 谢谢,我确实看过 AutoMapper,认为自定义扩展会提供更多控制。很想知道 Automapper 如何解决这个问题。
  • 你也有同样的事情,首先实现你的实体,然后通过 AutoMapper 运行它以获取映射的类。
  • 为了更清楚,你的意思是说 AutoMapper 也做了类似于@stybol 在下面的答案中建议的事情吗?利用AsEnumerable
  • 不是你会做类似var queryResults = someQueryHere 然后你会做var realResutls = Mapper.Map&lt;List&lt;DesiredType&gt;&gt;(queryResults);

标签: c# entity-framework linq


【解决方案1】:

在正常情况下,在 EntityFramework 中执行类似Where 的操作时,它实际上不会像操作枚举(如列表)时那样在内存中执行。相反,它转换为 SQL,然后由 Db 提供程序执行。这意味着做某些事情(例如对对象使用扩展方法)不是一种选择,因为转换器无法将这些事情转换为 SQL。

最快和最简单的解决方案是将您的集合加载到内存中,在那里它可以像任何其他枚举一样被操作。你可以这样做:

var result = myDbSet.AsEnumerable().Etc()

Etc() 在这里代表您要运行的所有其他操作。但是请注意,这会将所有数据加载到内存中,这在某些情况下可能会非常缓慢且昂贵。缓解这种情况的一种方法是将AsEnumerable()right放在您需要使用扩展方法之前,从而将尽可能多的操作卸载给提供者。比如这个:

var result = myDbSet.Where([condition]).AsEnumerable().Select(item => item.ExtensionMethod());

可能比这更快更轻:

var result = myDbSet.AsEnumerable().Where([condition]).Select(item => item.ExtensionMethod());

【讨论】:

  • 我试过这个解决方案,它给出了同样的错误:LINQ to Entities does not recognize the method and this method cannot be translated into a store expression.
  • 有问题的代码已更新为我正在使用的代码的确切副本,即使在选择查询之前添加 .AsEnumerable() 后也面临同样的问题。
  • @ShyamalParikh 你到底把.AsEnumerable()放在哪里?是放在x.Enums.Select 还是db.TableRows.Select 前面?
  • x.Enums.AsEnumerable().Select
  • @ShyamalParikh 您需要将它放在外部 Select 之前。 db.TableRows.AsEnumerable().Select
【解决方案2】:

您在 EF 中使用扩展方法的能力有限,但您仍然可以扩展您的 IQueryables

public static class Extensions
{
    public static IQueryable<MyModelVM> SelectVMs(this IQueryable<MyModel> models)
    {
        return models.Select(x => new MyModelVM { MyModelId = x.MyModelId });
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多