实体框架 LINQ 字符串顺序比较
本文关键字:顺序 比较 字符串 LINQ 框架 实体 | 更新日期: 2023-09-27 18:32:06
我的表中有一个varchar(5)
列(名为name
),名为codes
)。此 SQL 查询是我想通过 EF 完成的,而无需先将IQueryable
转换为IEnumerable
(在内存中):
SELECT * FROM codes WHERE name >= 'J0000' AND name <= 'J9999'
我尝试使用此方法执行查询,如下所示:
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()
我能想到的唯一其他选择是使用 .SqlQuery() 在我的数据库中。对 DbSet 进行编码,以便使用>= 和 <= 执行实际的选择语句。
是否有任何非 sql 选项可以让我执行这样的查询?
编辑:在我的实际代码中,我正在做一个.CompareTo(codes[0]),其中 codes 是一个字符串数组。此数组正在破坏 EF sql 转换。我的解决方案是先将字符串值放入新的字符串变量中,然后将新字符串变量传递给 .CompareTo() 而不是指定的数组变量/索引。
您可以使用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)