使用 SQL Server 数据库将 SQL 查询转换为 Linq

Posted

技术标签:

【中文标题】使用 SQL Server 数据库将 SQL 查询转换为 Linq【英文标题】:Converting a SQL query to Linq using a SQL Server database 【发布时间】:2021-09-14 21:29:48 【问题描述】:
select * 
from Enrollment 
where Atnper <= 70

我在 linq 中尝试了这个,但我得到一个错误:

var atn = db.Enrollments
            .Where(a => a.cid == cid && 
                        a.Section == sect && 
                        int.Parse(a.Atnper)<= 75)
            .Select(m => m.Atnper);

这是我得到的错误:

System.InvalidOperationException:“ObjectContent`1”类型无法序列化内容类型“application/json”的响应正文; charset=utf-8'。

SystemNotSupportedException:LINQ to Entities 无法识别方法“Int32 Parse(System.String)”方法,并且该方法无法转换为存储表达式。

堆栈跟踪 在 System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.DefaultTranslator.Translate(ExpressionConverter parent, MethodCallExpression call) 在 System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter 父级,MethodCallExpression linq) 在 System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(表达式 linq)\r\n 在 System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.BinaryTranslator.TypedTranslate(ExpressionConverter 父级,BinaryExpression linq)\r\n at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(表达式 linq)\r\n 在 System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.BinaryTranslator.TypedTranslate(ExpressionConverter 父级,BinaryExpression linq)\r\n at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(表达式 linq)\r\n 在 System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda,DbExpression 输入)\r\n at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter 父级、MethodCallExpression 调用、DbExpression& 源、 DbExpressionBinding& sourceBinding, DbExpression& lambda)\r\n at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter 父,MethodCallExpression 调用)\r\n at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter 父,MethodCallExpression linq)\r\n at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(表达式 linq)\r\n 在 System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter 父级、MethodCallExpression 调用、DbExpression& 源、 DbExpressionBinding& sourceBinding, DbExpression& lambda)\r\n at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SelectTranslator.Translate(ExpressionConverter 父,MethodCallExpression 调用)\r\n at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter 父,MethodCallExpression linq)\r\n at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(表达式 linq)\r\n 在 System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.Convert()\r\n 在 System.Data.Entity.Core.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable1 forMergeOption)\r\n at System.Data.Entity.Core.Objects.ObjectQuery1.c__DisplayClass7.b__6()\r\n 在 System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess)\r\n at System.Data.Entity.Core.Objects.ObjectQuery1.c__DisplayClass7.b__5()\r\n 在 System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func1 operation)\r\n at System.Data.Entity.Core.Objects.ObjectQuery1.GetResults(Nullable1 forMergeOption)\r\n at System.Data.Entity.Core.Objects.ObjectQuery1.b__0()\r\n 在 System.Data.Entity.Internal.LazyEnumerator`1.MoveNext()\r\n 在 Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList(JsonWriter writer,IEnumerable 值,JsonArrayContract 合同,JsonProperty 成员,JsonContainerContract 集合合同,JsonProperty containerProperty)\r\n 在 Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter,对象值,类型 objectType)\r\n at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter,对象值,类型 objectType)\r\n at System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream(类型 类型、对象值、流 writeStream、编码 有效编码)\r\n 在 System.Net.Http.Formatting.JsonMediaTypeFormatter.WriteToStream(类型 类型、对象值、流 writeStream、编码 有效编码)\r\n 在 System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStreamAsync(类型 类型、对象值、流 writeStream、HttpContent 内容、 TransportContext transportContext, CancellationToken cancelToken)\r\n--- 来自先前位置的堆栈跟踪结束 抛出异常的地方 ---\r\n 在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)\r\n 在 System.Web.Http.WebHost.HttpControllerHandler.d__22.MoveNext()"

【问题讨论】:

你检查过你的错误 AtnPer 是数据库中的数字字符串吗?它总是数字吗?将其转换为 int 列类型并修复您的实体以使用 int 属性并删除 int.Parse 你用的是什么版本的EF? 需要有关类模型、映射、EF 版本、数据类型的详细信息。此外,还有很多关于“LINQ to Entities 无法识别方法......”的问题。您是否尝试过自己寻找答案? 【参考方案1】:

从错误看来,您使用的是 EF6 或更早版本。我认为 EF 没有内置方法来调用字符串到数字的转换,但是您可以创建一个用户定义的函数来执行它并调用它 - 请参阅 https://docs.microsoft.com/en-us/previous-versions/dotnet/netframework-4.0/dd456847(v=vs.100) (但要解决可能的问题需要做很多工作数据建模中的缺陷))

--

您可以升级到 EF 核心并将您的 int.Parse 更改为 Convert.ToInt32(a.AtnPer),以便 EFC 将在 db 端使用 CONVERT(int, AtnPer),但是要解决数据建模中可能存在的缺陷需要做很多工作


如果您的列始终将 int 存储在字符串中,请将其更改为 int 类型列并将您的 C# 实体更改为 int

如果你在你的实体中犯了一个错误,db列是一个int,而实体是一个字符串,然后将实体修复为int并删除int解析

这里是您可以在 EFC LINQ 中使用的函数列表,因为它知道如何将它们转换为 sql server 中的某些内容:https://docs.microsoft.com/en-us/ef/core/providers/sql-server/functions

对于旧版 EF https://docs.microsoft.com/en-us/previous-versions/dotnet/netframework-4.0/dd456828(v=vs.100)?redirectedfrom=MSDN 的类似建议

【讨论】:

【参考方案2】:

这样的另一种方式:

var atn = db.Enrollments
            .Where(a => a.cid == cid && 
                        a.Section == sect && 
                        a.Atnper.Lenght <= 2 && 
                        a.Atnper <= "75")
            .Select(m => m.Atnper);

【讨论】:

请记住,字符串排序不同于整数排序。 "100" &lt; "75" 为真,100 &lt; 75 为假。这正是他们尝试解析字符串的原因。 当然,这就是我添加a.Atnper.Lenght &lt;= 2 的原因,但看起来这不正确。试试这个:(a.Atnper.Lenght &lt; 2 || (a.Atnper.Lenght == 2 &amp;&amp; a.Atnper &lt;= "75")) 是的,但这是一个不切实际的限制。

以上是关于使用 SQL Server 数据库将 SQL 查询转换为 Linq的主要内容,如果未能解决你的问题,请参考以下文章

使用 LIKE 将 Oracle 查询转换为 SQL Server 查询

SQL Server 2008 R2 - 将查询结果保存为 phpmyadmin 可读的 SQL 语句?

如何将查询从 phpMyAdmin SQL Dump 转换为 sql server 易读查询

将查询从 SQL Server 转换为 Access 2000

如何在SQL Server 2005中回滚UPDATE查询?

从 SQL Server Management Studio 查询两个单独的 SQL Compact 数据库