我正在使用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端执行它,而不是枚举代码中的所有对象。请有人能建议我如何实现这一目标吗?
答案 0 :(得分:0)
您可以先为_ratingsProvider.GetRating
分配一个变量,以避免标题错误。
此后,您将看到另一个错误,指出实体框架不支持您的查询。您需要类似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);
}