c# - 无法将类型为 'System.Linq.Expressions.MethodCallExpression' 的对象转换为类型 'System.Linq.Expressions.LambdaExpression'

标签 c# sql entity-framework linq entity-framework-6

我正在使用 EntityFramework 并遇到上述错误。当我调用

var documents = docRepository.GetAllSavedDocuments();
var withRatings = documentFilter.GetDocumentsWithRating(documents, 1);

我得到标题中的错误。

我的代码分为几个类

public class DocRepository
{
    public IQueryable<Document> GetAllSavedDocuments(User user)
    {
        return (from d in AllUsersDocuments(user)
                select d)
            .Include(d => d.Calculations)
            .Include("Calculations.CalculationResults");
    }
}

public class DocumentFilter
{
    public IQueryable<Tuple<Document, Rating>> GetDocumentsWithRating(IQueryable<Document> documents, int id)
    {
        return documents.Select(x => new
        {
            Document = x,
            Rating = _ratingsProvider.GetRating.Compile()(x, id)
        }).AsEnumerable()
            .Select(x => new Tuple<Document, Rating>(x.Document, x.Rating)).AsQueryable().Where(x.Item2 == Rating.Ok);
    }
}

public class RatingProvider
{
    public Expression<Func<Document, int, Rating>> GetRating
    {
        get
        {
            return (document, id) =>
                document.Calculations.Where(x => x.CId == id).Any() ?
                document.Calculations.Single(x => x.CId == id).Rating.Value :
                Rating.Unknown;
        }
    }
}

额外信息

评级是一个枚举。它在 Calculation 类上可以为空。我最初有 IEnumerable,所以我可以使用 Rating Provider 类中的方法进行过滤,例如:

var c = document.Calculations.SingleOrDefault(x => x.Id == id);
if (c == null)
{
    return Rating.None;
}
if (!c.Rating.HasValue)
{
    return Rating.None
}
return c.Rating.Value;

但我想让它保持可查询状态,因此我们在 SQL 端执行它,而不是在代码中枚举所有对象。有人可以建议我如何实现这一目标吗?

最佳答案

可以先为_ratingsProvider.GetRating赋值,避免标题错误。

之后您将遇到另一个错误,提示 Entity Framework 不支持您的查询。你需要像 LINQKit https://github.com/scottksmith95/LINQKit 这样的东西. AsExpandable()Invoke(x, id) 来自 LINQKit。

using LinqKit;
    public IQueryable<Tuple<Document, Rating>> GetDocumentsWithRating(IQueryable<Document> documents, int id)
    {
        var getRatingExpression = _ratingsProvider.GetRating;
        return documents.AsExpandable().Select(x => new
        {
            Document = x,
            Rating = getRatingExpression.Invoke(x, id)
        }).AsEnumerable()
            .Select(x => new Tuple<Document, Rating>(x.Document, x.Rating)).AsQueryable().Where(x.Item2 == Rating.Ok);
    }

第二个问题的答案:

    public Expression<Func<Document, int, Rating>> GetRating
    {
        get
        {
            return (document, id) =>
                document.Calculations.Where(x => x.CId == id).Any() ?
                document.Calculations
                        .Where(x => x.CId == id)
                        .Select(x => x.Rating.HasValue ? x.Rating.Value : Rating.None)
                        .Single()
                Rating.Unknown;
        }
    }

第二个问题的 .AsEnumerable() 部分的答案: 我猜你的问题来自于使用 Tuple,尝试定义一个类

public class DocumentRating
{
    public Document { get; set; }
    public Rating { get; set; }
}
    public IQueryable<DocumentRating> GetDocumentsWithRating(IQueryable<Document> documents, int id)
    {
        var getRatingExpression = _ratingsProvider.GetRating;
        return documents.AsExpandable().Select(x => new DocumentRating
        {
            Document = x,
            Rating = getRatingExpression.Invoke(x, id)
        })
        .Where(x.Item2 == Rating.Ok);
    }

关于c# - 无法将类型为 'System.Linq.Expressions.MethodCallExpression' 的对象转换为类型 'System.Linq.Expressions.LambdaExpression',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54242254/

相关文章:

c# - 长期使用Entities时在C#中使用EntityFramework

c# - 如何在不使用 Entity Framework 获取值本身的情况下获取 blob 大小

c# - EF N 层架构

c# - 将 C# 连接到远程 MySQL 数据库

C# 创建客户端作为 windowsservice

c# - Silverlight 调试问题

C#为DSA加密算法生成公钥和私钥

sql - MySQL全文搜索三个或更少字母的单词

java - JPA 查询验证日期以及自该日期以来的天数是否> 50

php - 计算给定标准费率和季节性日期范围的价格