c# - EntityFramework LINQ 字符串顺序比较

标签 c# sql .net entity-framework

我的表(名为 codes)中有一个 varchar(5) 列(名为 name)。这个 SQL 查询是我想通过 EF 完成的,无需先将我的 IQueryable 转换为 IEnumerable(在内存中):

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(),以便使用 >= 和 <= 执行实际的选择语句。

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

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

最佳答案

您可以使用 CompareTo 比较你的字符串。 Entity Framework 将这些转换为 > , < , >=<= .

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)

关于c# - EntityFramework LINQ 字符串顺序比较,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27128836/

相关文章:

c# - HttpHandler - 大型 Xml - 标记已损坏

c# - 在 CosmosDB 文档的字典中查询项目

c# - 使用 C# 恢复 SQL 数据库

c# - 当类具有 IDisposable 成员但没有非托管资源时,我应该实现 IDisposable 吗?

c# - 防止其他开发人员在类中使用基方法

mysql - 连接返回空值?

mysql - 如何将列名与其他参数一起传递

java - 如何使用可完成的 future 异步运行方法

c# - 带有泛型的类型化类

c# - 使用 XML 作为数据存储的自定义提供程序——我应该使用 XPath/XSLT 还是 DOM?