context.Database.SqlQuery<>()查询

本文探讨了使用EF Core进行数据库查询时遇到的问题:当实体类与查询语句不完全匹配时产生的错误及解决方法。特别关注了实体类与自定义模型在查询中的表现差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

public class Student 
    {
        public int ID { get; set; }

        public string Name { get; set; }

        public int Age { get; set; }

    }

ctx.Database.SqlQuery<Student>("select Name,Age from student", parameter).ToList();
1、如果Student是实体类的话,上面语句会报错误-{"数据读取器与指定的“Student”不兼容。类型“ID”的成员在同名的数据读取器中没有对应的列。"}	System.Data.Entity.Core.EntityException {System.Data.Entity.Core.EntityCommandExecutionException},必须在查询的语句中包含所有实体中的列名
2、如果Student是自定义的贫血模型,上面语句则不会报错
Microsoft.Data.SqlClient.SqlException (0x80131904): 对象名 'Receive' 无效。 at Microsoft.Data.SqlClient.SqlCommand.<>c.<ExecuteDbDataReaderAsync>b__195_0(Task`1 result) at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke() at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) --- End of stack trace from previous location --- at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread) --- End of stack trace from previous location --- at Dapper.SqlMapper.QueryAsync[T](IDbConnection cnn, Type effectiveType, CommandDefinition command) in /_/Dapper/SqlMapper.Async.cs:line 434 at Finance.Infrastructure.DapperDb.Query[T](String sql, Object parameters) in D:\2211A实训一\项目\erp\财务管理\Finance.Infrastructure\DapperDb.cs:line 23 at Finance.Api.Read.Applications.CommandHands.ReceiveQueryCommandHandlers.Handle(ReceiveQueryCommand request, CancellationToken cancellationToken) in D:\2211A实训一\项目\erp\财务管理\Finance.Api.Read\Applications\CommandHands\ReceiveQueryCommandHandlers.cs:line 32 at Finance.Api.Read.Controllers.ManagementController.ReceiveQuery(ReceiveQueryCommand request) in D:\2211A实训一\项目\erp\财务管理\Finance.Api.Read\Controllers\ManagementController.cs:line 26 at lambda_method5(Closure, Object) at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(ActionContext actionContext, IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope) at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context) at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext) at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider) at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context) ClientConnectionId:2a4e1948-5a2d-453c-a4b3-616d63e0b80c Error Number:208,State:1,Class:16 HEADERS ======= Accept: text/plain Connection: keep-alive Host: localhost:5047 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Accept-Encoding: gzip, deflate, br, zstd Accept-Language: zh-CN,zh;q=0.9 Referer: http://localhost:5047/swagger/index.html sec-ch-ua-platform: "Windows" sec-ch-ua: "Not)A;Brand";v="8", "Chromium";v="138", "Google Chrome";v="138" sec-ch-ua-mobile: ?0 Sec-Fetch-Site: same-origin Sec-Fetch-Mode: cors Sec-Fetch-Dest: empty
最新发布
07-23
<think>我们遇到一个SQL异常:对象名 'Receive' 无效。这意味着在查询中引用的表或视图名 'Receive' 在数据库中不存在。 错误堆栈指向了DapperDb的Query方法,具体在ReceiveQueryCommandHandlers的第32行和ManagementController的第26行。 可能的原因: 1. 数据库中没有名为 'Receive' 的表(可能是表名错误、表不存在,或者数据库连接到了错误的数据库)。 2. 表名大小写问题(如果数据库是大小写敏感的,而代码中写的大小写与实际表名不一致)。 3. 表不在当前用户的默认模式(Schema)下,需要指定模式名(例如:dbo.Receive)。 根据错误信息,我们需要检查: - 数据库连接字符串是否正确,是否连接到了正确的数据库。 - 数据库中是否存在名为 'Receive' 的表,或者表名是否拼写错误(例如:实际表名可能是Receives、Receipt等)。 - 如果表在特定的模式(如dbo)下,在查询时应该使用模式名限定(如:SELECT * FROM dbo.Receive)。 解决方案: 1. 检查数据库中的表名:连接到数据库,执行查询(如:SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Receive')看是否存在。 2. 如果表在非默认模式(如不是dbo),则在查询中指定模式名。 3. 检查代码中的SQL语句:在ReceiveQueryCommandHandlers的第32行和ManagementController的第26行,查看执行的SQL语句是什么。 例如,在代码中可能写的是: var sql = "SELECT * FROM Receive"; 而实际上,表名可能是 "Receives" 或者 "dbo.Receive",那么需要修改为正确的表名。 另外,也要注意SQL注入问题,避免直接拼接字符串,但这里表名是固定的,可以使用参数化查询来避免,但表名本身不能参数化,所以需要确保表名的正确性。 根据堆栈信息,我们定位到代码位置: - Finance.Api.Read.Applications.CommandHands.ReceiveQueryCommandHandlers.Handle 方法 - Finance.Api.Read.Controllers.ManagementController.ReceiveQuery 方法 因此,我们需要检查这些地方的SQL字符串。 如果表名确实为Receive,但在默认模式下找不到,可以尝试: SELECT * FROM [Receive] -- 使用方括号避免关键字冲突 SELECT * FROM dbo.Receive -- 指定模式 另外,注意在SQL Server中,表名是大小写不敏感的(除非安装时指定了区分大小写),所以大小写通常不是问题。 步骤: 1. 打开SQL Server Management Studio 或使用其他工具连接到数据库。 2. 运行:USE [YourDatabaseName] 然后执行:SELECT * FROM sys.tables WHERE name = 'Receive' 查看表是否存在。 3. 如果不存在,检查迁移脚本或数据库创建脚本,确认表名是否正确创建。 如果表不存在,需要创建表或修复表名。 如果表存在,那么检查连接字符串中的数据库名称是否正确。 代码示例修正: 假设表名应该是 'Receives',则修改SQL语句为: var sql = "SELECT * FROM Receives"; 或者如果表在dbo模式下: var sql = "SELECT * FROM dbo.Receive"; 另外,注意错误中的表名是单数,而数据库设计常用复数,所以很可能是表名应该是复数形式。 根据错误堆栈,我们还可以看到这是一个GET请求(通过Swagger调用),所以检查Swagger中调用的接口是否正确。 由于错误信息中提到了对象名'Receive'无效,所以重点检查该表名。 总结:这个错误是SQL对象未找到的典型错误,需要检查数据库中的对象是否存在以及代码中的SQL语句是否正确。</think>### 解决 "对象名 'Receive' 无效" 的 SQL 错误分析 #### 错误原因诊断 1. **核心问题** `SqlException (0x80131904): 对象名 'Receive' 无效` 表示数据库无法找到名为 "Receive" 的对象(表/视图)。错误代码 208 在 SQL Server 中表示 **对象不存在**。 2. **关键线索** - 堆栈跟踪指向 `ReceiveQueryCommandHandlers.cs:line 32` 和 `ManagementController.cs:line 26` - 执行位置:`DapperDb.Query<T>()` 方法 - 实际 SQL 语句:`SELECT * FROM Receive`(隐式在查询中) #### 解决方案步骤 ##### 1. 检查数据库对象是否存在 ```sql -- 检查表是否存在 SELECT * FROM sys.tables WHERE name = 'Receive' -- 检查视图是否存在 SELECT * FROM sys.views WHERE name = 'Receive' -- 检查架构绑定(默认 dbo) SELECT * FROM sys.objects WHERE name = 'Receive' AND schema_id = SCHEMA_ID('dbo') ``` ##### 2. 修正代码中的对象引用 ```csharp // 错误示例(缺少架构前缀) var sql = "SELECT * FROM Receive"; // 修正方案1:添加架构前缀 var sql = "SELECT * FROM dbo.Receive"; // 修正方案2:使用带架构的参数化方法 public async Task<IEnumerable<T>> GetByTableAsync<T>(string schema, string tableName) { return await _db.QueryAsync<T>($"SELECT * FROM {schema}.{tableName}"); } ``` ##### 3. 验证数据库连接配置 检查 `appsettings.json` 确保连接的是正确数据库: ```json { "ConnectionStrings": { "DefaultConnection": "Server=.;Database=YourFinanceDB;Integrated Security=true;" } } ``` ##### 4. 添加防御性编程 ```csharp // 在查询前验证对象存在 public async Task<IEnumerable<T>> SafeQueryAsync<T>(string tableName) { var exists = await _db.ExecuteScalarAsync<bool>( @"SELECT CASE WHEN EXISTS ( SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = @tableName ) THEN 1 ELSE 0 END", new { tableName }); if (!exists) throw new TableNotFoundException(tableName); return await _db.QueryAsync<T>($"SELECT * FROM dbo.{tableName}"); } ``` #### 常见原因排查表 | 原因 | 检查点 | 解决方案 | |------|--------|----------| | 缺少架构前缀 | 表是否在默认 dbo 架构 | 添加 `dbo.` 前缀 | | 大小写敏感 | 数据库是否区分大小写 | 统一使用正确大小写 | | 权限问题 | 当前用户是否有 SELECT 权限 | 授权 `GRANT SELECT ON Receive TO [User]` | | 数据库迁移未执行 | 表是否实际创建 | 检查数据库迁移脚本 | | 多数据库环境 | 连接字符串是否正确 | 验证连接字符串的数据库名 | #### 预防措施 1. **使用仓储模式** 封装表访问 2. **集中管理 SQL 语句** 在常量类中 ```csharp public static class FinanceSql { public const string GetAllReceives = "SELECT * FROM dbo.Receive"; } ``` 3. **集成测试** 验证数据库对象 ```csharp [Fact] public void Should_Have_Receive_Table() { using var conn = new SqlConnection(_config.ConnectionString); var exists = conn.ExecuteScalar<bool>( "SELECT COUNT(1) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Receive'"); Assert.True(exists); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

苍狼_2001

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值