我正在使用 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/