C# LINQ to实体不支持实体框架中的调用

C# LINQ to实体不支持实体框架中的调用,c#,entity-framework,linq,C#,Entity Framework,Linq,下面是我必须使用表达式的函数,但我认为实体框架不允许这样做。我已经在LINQtoSQL中使用了这个函数,它正在工作。我也尝试过使用LinqKit,因为这是我在许多答案中发现的,但错误仍然存在 public static IList<SelectListItem> From<T>(IQueryable<T> Source, Expression<Func<T, object>> Value, Expression<Func<T

下面是我必须使用表达式的函数,但我认为实体框架不允许这样做。我已经在LINQtoSQL中使用了这个函数,它正在工作。我也尝试过使用LinqKit,因为这是我在许多答案中发现的,但错误仍然存在

public static IList<SelectListItem> From<T>(IQueryable<T> Source, Expression<Func<T, object>> Value, Expression<Func<T, string>> Text)
{
    var q = from T item in Source
            select new SelectListItem()
            {
                Text = Text.Compile()((item)),
                Value = Value.Compile()((item)).ToString()
            };
    return q.ToList();
}
公共静态IList From(IQueryable源、表达式值、表达式文本)
{
var q=源中的T项
选择新的SelectListItem()
{
Text=Text.Compile()((项)),
Value=Value.Compile()((项)).ToString()
};
返回q.ToList();
}

当我通过将
List
转换为
IQueryable
将其作为源代码提供时,它会起作用

您可以通过以下方式解决您的问题:

public static IList<SelectListItem> From<T>(
    IQueryable<T> Source,
    Expression<Func<T, object>> Value,
    Expression<Func<T, string>> Text)
{
    var q = from T item in Source.AsExpandable()
            select new SelectListItem()
            {
                Text = Text.Invoke(item),
                Value = Value.Invoke(item).ToString()
            };

    return q.ToList();
}
var result =
    From(
        context.Customers,
        x => x.CustomerId,
        x => x.Name);
这是在SQL server上执行的SQL:

SELECT 
    [Extent1].[CustomerId] AS [CustomerId], 
    [Extent1].[Name] AS [Name], 
     CAST( [Extent1].[CustomerId] AS nvarchar(max)) AS [C1]
    FROM [dbo].[Customers] AS [Extent1]

您需要使用
System.Linq.Expressions
构建整个表达式

这里有一个函数可以做到这一点(我对类似问题的回答的修改版本):


您确定它在LinqToSQL中工作吗?你看过生成的SQL了吗?但是如果你真的想解决这个问题,那就很容易了。步骤很简单。只有第3步会有所不同。@Aron LINQ to SQL对无法转换为SQL的构造比EF宽容得多,而只是在客户端执行它们。如果它能“工作”于此,我一点也不会感到惊讶,SQL应该表明它只是请求整个
。LINQ-to-SQL正在做你想做的事情,但没有告诉你-它加载内存中的所有内容,然后将查询转换为LINQ-to-Objects。这可以消除性能,因为它可以在内存中加载许多不需要的对象。EF不允许这样做,并立即警告您。@hvd这正是我要说的……我已经尝试了LInqKit,但它也不起作用。在这种情况下,错误是“无法将'System.Linq.Expressions.InstanceMethodCallExpression'类型的对象强制转换为'System.Linq.Expressions.LambdaExpression'你是否完全按照原样使用我答案中的代码?我已经在本地测试了这段代码,它可以正常工作。您能显示您当前拥有的代码吗?
public static class Utils
{
    public static IList<SelectListItem> ToSelectList<TSource, TValue>(this IQueryable<TSource> source, Expression<Func<TSource, TValue>> valueSelector, Expression<Func<TSource, string>> textSelector)
    {
        var itemValue = valueSelector.Body;
        if (itemValue.Type != typeof(string))
            itemValue = Expression.Call(itemValue, itemValue.Type.GetMethod("ToString", Type.EmptyTypes));
        var itemText = textSelector.Body.ReplaceParameter(textSelector.Parameters[0], valueSelector.Parameters[0]);
        var targetType = typeof(SelectListItem);
        var selector = Expression.Lambda<Func<TSource, SelectListItem>>(
            Expression.MemberInit(Expression.New(targetType),
                Expression.Bind(targetType.GetProperty("Value"), itemValue),
                Expression.Bind(targetType.GetProperty("Text"), itemText)
            ), valueSelector.Parameters);
        return source.Select(selector).ToList();
    }

    static Expression ReplaceParameter(this Expression expression, ParameterExpression source, Expression target)
    {
        return new ParameterExpressionReplacer { source = source, target = target }.Visit(expression);
    }

    class ParameterExpressionReplacer : ExpressionVisitor
    {
        public ParameterExpression source;
        public Expression target;
        protected override Expression VisitParameter(ParameterExpression node)
        {
            return node == source ? target : base.VisitParameter(node);
        }
    }
}
public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
}

var result = db.Persons.ToSelectList(p => p.Id, p => p.Name);