使用EntityFramework.Cosmos的FromSqlRaw传参返回0结果问题排查
解决EntityFramework.Cosmos中FromSqlRaw参数化查询返回0的问题
问题描述
我正在使用EntityFramework.Cosmos,因需求必须使用FromSqlRaw()扩展方法执行原生查询,示例代码如下:
Guid partnerId = new Guid([myPartnerId]) // 字符串插值查询 var queryString = $@"SELECT * FROM c WHERE c.Discriminator = 'testEntity' AND c.PartnerId = '{partnerId}' "; int totalCount = await _context.testEntity.FromSqlRaw(queryString).CountAsync(); // 返回73条结果 var parameters = new List<SqlParameter> { new SqlParameter("@Discriminator", "testEntity"), new SqlParameter("@PartnerId", partnerId.ToString()) }; // 参数化查询 var queryStringParameterized = $@"SELECT * FROM c WHERE c.Discriminator = @Discriminator AND c.PartnerId = @PartnerId "; int totalCountParameterized = await _context.testEntity.FromSqlRaw(queryStringParameterized, parameters.ToArray()).CountAsync(); // 返回0条结果
执行后,字符串插值查询返回73条结果,但参数化查询返回0条结果,请问哪里操作有误?
问题原因
- 参数类型用错:
SqlParameter是SQL Server专属的参数类,Cosmos DB无法识别该类型,导致参数无法正确绑定到查询语句中,相当于条件没生效。 - Guid处理不当:你把
partnerId转成字符串传入参数,若Cosmos中存储的PartnerId是原生Guid类型,字符串和Guid类型直接比对会不匹配;就算存的是字符串,SqlParameter也会导致参数传递异常。
正确解决方法
方法一:匿名类型传递命名参数
直接用匿名对象封装参数,EF Core会自动处理Cosmos的参数绑定逻辑:
Guid partnerId = new Guid([myPartnerId]); int totalCountParameterized = await _context.testEntity .FromSqlRaw(@"SELECT * FROM c WHERE c.Discriminator = @Discriminator AND c.PartnerId = @PartnerId", new { Discriminator = "testEntity", PartnerId = partnerId }) .CountAsync();
方法二:使用位置参数
通过{0}、{1}这类位置占位符,直接传递对应参数值:
Guid partnerId = new Guid([myPartnerId]); int totalCountParameterized = await _context.testEntity .FromSqlRaw(@"SELECT * FROM c WHERE c.Discriminator = {0} AND c.PartnerId = {1}", "testEntity", partnerId) .CountAsync();
注意:不用把Guid转成字符串,直接传原生
Guid类型就行,EF Core会自动匹配Cosmos中的存储类型(不管是原生Guid还是字符串格式的Guid,只要类型对应就能正确匹配)。
内容的提问来源于stack exchange,提问作者Humzamanzur
相关产品推荐
相关产品推荐

