2014-11-25 80 views
4

我在我的表(名为codes)中有一个varchar(5)列(名为name)。这个SQL查询是希望我通过EF来完成,而无需首先转换到IQueryableIEnumerable(在内存中)我:EntityFramework LINQ字符串顺序比较

SELECT * FROM codes WHERE name >= 'J0000' AND name <= 'J9999' 

我试着执行使用this method查询,像这样:

var results = db.Codes.Where(c=>c.Name.CompareTo("J0000") >=0 
    && c.Name.CompareTo("J9999") <=0) 

但是,CompareTo不能被转换成sql并抛出异常。为了使CompareTo工作,必须具有IEnumerable,这意味着所有记录都已从数据库中提取到内存中。当尝试执行此我得到:

{"The LINQ expression node type 'ArrayIndex' is not supported in LINQ to Entities."} 

带有堆栈跟踪:

at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.NotSupportedTranslator.Translate(ExpressionConverter parent, Expression linq) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.BinaryTranslator.TypedTranslate(ExpressionConverter parent, BinaryExpression 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.BinaryTranslator.TypedTranslate(ExpressionConverter parent, BinaryExpression 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, DbExpressionBinding& binding) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, DbExpression& source, DbExpressionBinding& sourceBinding, 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.Convert() 
    at System.Data.Entity.Core.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable`1 forMergeOption) 
    at System.Data.Entity.Core.Objects.ObjectQuery`1.<>c__DisplayClass7.<GetResults>b__6() 
    at System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func`1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess) 
    at System.Data.Entity.Core.Objects.ObjectQuery`1.<>c__DisplayClass7.<GetResults>b__5() 
    at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func`1 operation) 
    at System.Data.Entity.Core.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption) 
    at System.Data.Entity.Core.Objects.ObjectQuery`1.<System.Collections.Generic.IEnumerable<T>.GetEnumerator>b__0() 
    at System.Data.Entity.Internal.LazyEnumerator`1.MoveNext() 
    at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext() 

我,我能想到的唯一的其他选择是为了我的db.Codes DbSet使用.SqlQuery()使用> =和< =执行实际的select语句。

是否有任何非sql选项可以让我执行这样的查询?

编辑:在我的实际代码中,我做了一个.CompareTo(代码[0]),其中代码是一个字符串数组。这个数组打破了EF sql的翻译。我的解决方案是先将字符串值转换为新的字符串变量,然后将新的字符串变量传递给.CompareTo()而不是指定的数组变量/索引。

+0

你就不能这样做'c.Name> =“J0000''在LINQ而不是'CompareTo' – DLeh 2014-11-25 14:15:57

+1

@DLeh c.Name?是一个字符串,你不能在c#中用这种方式比较字符串,而且它需要被EF内部翻译为sql。 – Rafe 2014-11-25 14:18:36

+0

我的错误,我想到了javascript我想。 – DLeh 2014-11-25 14:20:31

回答

3

您可以使用CompareTo来比较你的字符串。实体框架将这些转换成>,<,>=<=

var results = db.Codes.Where(c => c.Name.CompareTo("J0000") >= 0); 

或使用此语法:

var results = from c in db.Codes 
       where c.Name.CompareTo("J0000") >= 0 
       select c; 

这将产生类似这样的SQL输出:

WHERE [Extent1].[Name] >= N'J0000' 

编辑

你给你的错误消息之后似乎您正在使用索引属性而不是字符串文字在你的Linq查询中。要解决此问题,请将值复制到临时变量。所以这个:

var results = db.Codes.Where(c=> c.Name.CompareTo(somearray[0]) >=0 
           && c.Name.CompareTo(somearray[1]) <=0) 

变为这样:

var lowerBound = somearray[0]; 
var upperBound = somearray[1]; 

var results = db.Codes.Where(c=> c.Name.CompareTo(lowerBound) >=0 
           && c.Name.CompareTo(upperBound) <=0)