Почему я получаю InvalidCastException при использовании выражения из статического поля?
Я только начинаю использовать LinqKit с EntityFramework 6.0.2 и у меня следующий вопрос...
Почему это:
public static readonly Expression<Func<MyEnum, string>> ConvertToString = e =>
e == MyEnum.One
? "one"
: e == MyEnum.Two
? "two"
: "zero";
private static string GetSomethingElse(IQueryable<EnumTest> things)
{
var ret = things
.AsExpandable()
.Select(c => Program.ConvertToString.Invoke(c.SomeEnum))
.First();
return ret;
}
бросить:
An unhandled exception of type 'System.InvalidCastException'
occurred in LinqKit.dll
Additional information: Unable to cast object of type
'System.Linq.Expressions.FieldExpression' to type
'System.Linq.Expressions.LambdaExpression'.
но это:
private static string GetSomething(IQueryable<EnumTest> things)
{
Expression<Func<MyEnum, string>> ConvertToString = e => e == MyEnum.One
? "one"
: e == MyEnum.Two
? "two"
: "zero";
var ret = things
.AsExpandable()
.Select(c => ConvertToString.Invoke(c.SomeEnum))
.First();
return ret;
}
работает отлично?
1 ответ
Это потому, что внутри вашего выражения вы получаете доступ к полю. Исключение говорит вам, что вы получаете доступ к полю.
Выражение не оценивается при создании запроса. Это выполняется только после того, как вы выполните его. На этом этапе ему нужно будет разрешить поле. Обходной путь - сначала получить выражение в локальной переменной:
private static string GetSomething(IQueryable<EnumTest> things)
{
var expression = Program.ConvertToString;
var ret = things
.AsExpandable()
.Select(c => expression.Invoke(c.SomeEnum))
.First();
return ret;
}
Видя, что вы используете это с EntityFramework, вы получите то, что ваше выражение будет преобразовано в SQL-запрос. Однако, поскольку вы обращаетесь к классу внутри выражения, он не может преобразовать его в оператор SQL (как он это сделает?). Когда у вас есть экземпляр выражения (с локальной переменной), вы исключаете доступ к этому классу, и это выражение можно преобразовать в SQL.