score:2

you can assign a variable for _ratingsprovider.getrating first, to avoid the error in the title.

after that you will have another error saying entity framework does not support your query. you need something like linqkit https://github.com/scottksmith95/linqkit. asexpandable() and invoke(x, id) are from 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);
    }

answer to your second question:

    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;
        }
    }

answer to the .asenumerable() part of your second question: i guess the problem you had came from the use of tuple<document, rating>, try to define a class

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);
    }

Related Query

More Query from same tag