LINQ to Entities方法无法识别 - 扩展方法样式

ste*_*lla 3 c# linq linq-to-entities entity-framework

这是另一个"LINQ to实体无法识别方法问题"......但是,下面的代码不是从根本上做同样的事情吗?

作品:

var returnData = from x in MyEntities.MyDBSet
                        where x.MyDBSetPrimaryKey == id
                        select new Models.MyModelDTO
                        {
                            MyPropOne = (int)x.MyModel.MyOtherPropOne,
                            MyPropTwo = x.MyOtherPropTwo ?? 0,
                            MyPropThree = x.MyModel.MyOtherPropThree,
                            MyPropFour = x.MyModel.MyOtherPropFour,
                            MyPropFive = x.MyModel.Entity.MyOtherPropFive,
                            MyPropSix = x.MyModel.MyOtherPropSix == null ? 0 : (decimal)x.MyModel.MyOtherPropSix,
                            MyPropSeven = x.MyModel.SomeType.MyOtherPropSeven,
                            MyPropEight = (int)x.MyModel.MyOtherPropEight,
                            MyPropNine = x.MyModel.MyPropNine == null ? 0 : (int)x.MyModel.MyOtherPropNine,
                            MyPropTen = x.MyModel.MyOtherPropTen == null ? 0 : (int)x.MyModel.MyOtherPropTen,
                            MyPropEleven = x.OtherEntity.MyOtherPropEleven,
                            MyPropTwelve = x.MyOtherpropTwelve
                        };
Run Code Online (Sandbox Code Playgroud)

不起作用:

包含在扩展方法中的完全相同的赋值:

public static MyModelDTO ToModelDTO(this MyModel x)
    {
        return new MyModelDTO()
        {
            MyPropOne = (int) x.MyModel.MyOtherPropOne,
            MyPropTwo = x.MyOtherPropTwo ?? 0,
            MyPropThree = x.MyModel.MyOtherPropThree,
            MyPropFour = x.MyModel.MyOtherPropFour,
            MyPropFive = x.MyModel.Entity.MyOtherPropFive,
            MyPropSix = x.MyModel.MyOtherPropSix == null ? 0 : (decimal) x.MyModel.MyOtherPropSix,
            MyPropSeven = x.MyModel.SomeType.MyOtherPropSeven,
            MyPropEight = (int) x.MyModel.MyOtherPropEight,
            MyPropNine = x.MyModel.MyPropNine == null ? 0 : (int) x.MyModel.MyOtherPropNine,
            MyPropTen = x.MyModel.MyOtherPropTen == null ? 0 : (int) x.MyModel.MyOtherPropTen,
            MyPropEleven = x.OtherEntity.MyOtherPropEleven,
            MyPropTwelve = x.MyOtherpropTwelve
        };
    }
Run Code Online (Sandbox Code Playgroud)

后来又称:

var returnData = from x in MyEntities.MyDBSet
                        where x.MyDBSetPrimaryKey == id
                        select x.ToModelDto();
Run Code Online (Sandbox Code Playgroud)

导致:

LINQ to Entities does not recognize the method 'MyExtensionMethods.MyModels.MyModelDTO ToModelDTO(API.Models.MyModel)' method, and this method cannot be translated into a store expression.
Run Code Online (Sandbox Code Playgroud)

Ser*_*rvy 6

当查询提供程序看到该方法时,它不知道如何处理它.它无法进入并查看方法的源代码,它可以查看Expression对象的方式以及查看已完成的操作.它无法在客户端评估它,因为它还没有项目,并且它无法想到任何SQL将该方法调用转换为.

相反,你应该编写一个方法来获取IQueryable和返回另一个IQueryable,如下所示:

public static IQueryable<MyModelDTO> ToModelDTO(this IQueryable<MyModel> query)
{
    return query.Select(x => new MyModelDTO()
    {
        MyPropOne = (int)x.MyModel.MyOtherPropOne,
        MyPropTwo = x.MyOtherPropTwo ?? 0,
        MyPropThree = x.MyModel.MyOtherPropThree,
        MyPropFour = x.MyModel.MyOtherPropFour,
        MyPropFive = x.MyModel.Entity.MyOtherPropFive,
        MyPropSix = x.MyModel.MyOtherPropSix == null ? 0 : (decimal)x.MyModel.MyOtherPropSix,
        MyPropSeven = x.MyModel.SomeType.MyOtherPropSeven,
        MyPropEight = (int)x.MyModel.MyOtherPropEight,
        MyPropNine = x.MyModel.MyPropNine == null ? 0 : (int)x.MyModel.MyOtherPropNine,
        MyPropTen = x.MyModel.MyOtherPropTen == null ? 0 : (int)x.MyModel.MyOtherPropTen,
        MyPropEleven = x.OtherEntity.MyOtherPropEleven,
        MyPropTwelve = x.MyOtherpropTwelve
    });
}
Run Code Online (Sandbox Code Playgroud)

这里的映射仍然编译成Expression查询提供程序可以解析的.现在你可以这样做:

var returnData = (from x in MyEntities.MyDBSet
                  where x.MyDBSetPrimaryKey == id
                  select x)
                  .ToModelDTO();
Run Code Online (Sandbox Code Playgroud)