2014-10-01 3 views
1

Я пытаюсь получить доступ к значению контакта в запросе LINQ через отражение. Я использую .NET C#.Использовать значение из отражения в запросе LINQ

Итак, у меня есть класс данных, в котором я использую отражение, также получаю значение от свойства, имеющего определенный атрибут ([ConexioSearchField]).

Пример:

[ConexioSearchField] 
public string FullName { get; set; } 

Это код, где я сделать это прямо сейчас:

//Starting the Linq Query 
var unitOfWork = new SynchronizationUnitOfWork(_context); 
var repository = unitOfWork.RepositoryAsync<TC>(); 
var entities = repository.Queryable(); 

var firstOrDefault = EntityTypeDescriptorStore.GetEntityTypeDescriptor<TC>().Properties.FirstOrDefault(sf => sf.IsSearchField); 
if (firstOrDefault == null) return entities; 

var propertyInfo = firstOrDefault.PropertyInfo; 

entities = type == HandledType.Doubtful 
       ? entities.Where(entity1 => entity1.IsDoubtful && propertyInfo.GetValue(entity1).ToString().Contains(nameFilter)) 
       : entities.Where(entity1 => propertyInfo.GetValue(entity1).ToString().Contains(nameFilter)); 

Но это ошибка, что у меня есть:

Test method Conexio.Core.Orchestration.Test.Doubtfuls.SearchContactsTest.TestSearch3 threw 

exception: 
System.AggregateException: One or more errors occurred. ---> System.NotSupportedException: LINQ to Entities does not recognize the method 'System.Object GetValue(System.Object)' method, and this method cannot be translated into a store expression. 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.DefaultTranslator.Translate(ExpressionConverter parent, MethodCallExpression call) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.StringTranslatorUtil.ConvertToString(ExpressionConverter parent, Expression linqExpression) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.ToStringTranslator.Translate(ExpressionConverter parent, MethodCallExpression call) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateFunctionIntoLike(MethodCallExpression call, Boolean insertPercentAtStart, Boolean insertPercentAtEnd, Func`5 defaultTranslator) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.StringContainsTranslator.Translate(ExpressionConverter parent, MethodCallExpression call) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input, ref DbExpressionBinding binding) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, ref DbExpression source, ref DbExpressionBinding sourceBinding, ref DbExpression lambda) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, SequenceMethod sequenceMethod) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, ref DbExpression source, ref DbExpressionBinding sourceBinding, ref DbExpression lambda) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, SequenceMethod sequenceMethod) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.UnarySequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, SequenceMethod sequenceMethod) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.UnarySequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, SequenceMethod sequenceMethod) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.Convert() 
    at System.Data.Entity.Core.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable`1 forMergeOption) 
    at System.Data.Entity.Core.Objects.ObjectQuery`1.<>c__DisplayClassc.<GetResultsAsync>b__a() 
    at System.Data.Entity.Core.Objects.ObjectContext.<ExecuteInTransactionAsync>d__3d`1.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.<ExecuteAsyncImplementation>d__9`1.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Data.Entity.Utilities.TaskExtensions.CultureAwaiter`1.GetResult() 
    at System.Data.Entity.Core.Objects.ObjectQuery`1.<GetResultsAsync>d__e.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Data.Entity.Utilities.TaskExtensions.CultureAwaiter`1.GetResult() 
    at System.Data.Entity.Internal.LazyAsyncEnumerator`1.<FirstMoveNextAsync>d__0.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Data.Entity.Infrastructure.IDbAsyncEnumerableExtensions.<ForEachAsync>d__5`1.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() 
    at Conexio.Core.Orchestration.Contacts.Doubtfuls.SearchDoubtfuls`3.<SearchAsync>d__5.MoveNext() in SearchDoubtfuls.cs: line 59 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() 
    at Conexio.Core.Orchestration.Contacts.ConexioEntityBL`3.<SearchDoubtfulsAsync>d__28.MoveNext() in ConexioEntityBL.cs: line 323 
--- End of inner exception stack trace --- 
    at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions) 
    at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification) 
    at System.Threading.Tasks.Task`1.get_Result() 
    at Conexio.Core.Orchestration.Test.Doubtfuls.SearchContactsTest.TestSearch3() in SearchContactsTest.cs: line 77 

ответ

1

Расширения D Стэнли ответа на строительство выражения, здесь выражение.

var entity1 = Expression.Parameter(typeof(Entity)); 
var nameFilterExp = Expression.Call(
    Expression.Property(entity1, firstOrDefault.PropertyInfo.Name), 
    typeof(string).GetMethod("Contains", new[] { typeof(string) }), 
    Expression.Constant(nameFilter) 
); 
var predicate = Expression.Lambda<Func<Entity, bool>>(
    type == HandledType.Doubtful 
     ? (Expression)Expression.AndAlso(Expression.Equal(Expression.Property(entity1, "IsDoubtful"), Expression.Constant(true)), nameFilterExp) 
     : (Expression)nameFilterExp, 
    entity1); 
entities = entities.Where(predicate); 
4

Проблема заключается в том что EF пытается превратить ваши условия Where в предложения SQL WHERE и не знает что делать с вызовами отражения.

Несколько вариантов:

  1. Используйте кнопки propertyInfo для создания Expression что EF может перевести на SQL
  2. Использования Dynamic Linq
+0

Можете ли вы помочь мне, как я могу сделать свою правдивость в выражении? – kevingoos

+1

@Ghost Вы можете найти SO, чтобы найти несколько вопросов, связанных с этим. –

+0

@ D Stanley Я пытаюсь найти кого-то, у кого такая же проблема, но не может найти его :) – kevingoos

Смежные вопросы