我正在尝试针对本地 MSSQL 服务器执行存储过程,但我得到一个由
catch
块捕获的空数组,尽管在 SSMS
中执行时我返回了一条记录。
我得到的错误
System.InvalidOperationException:序列不包含元素 在 System.Linq.ThrowHelper.ThrowNoElementsException() 在 System.Linq.Enumerable.MaxInteger[T](IEnumerable1 源) 在 Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.VisitBinary(BinaryExpression 二进制表达式) 在 System.Dynamic.Utils.ExpressionVisitorUtils.VisitBlockExpressions(ExpressionVisitor 访问者,BlockExpression 块) 在 System.Linq.Expressions.ExpressionVisitor.VisitBlock(BlockExpression 节点) 在 Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.VisitExtension(表达式扩展Expression) 在 Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.ProcessShaper(表达式 shaperExpression、RelationalCommandCache& relationalCommandCache、IReadOnlyList 1& readerColumns、LambdaExpression& relatedDataLoaders、Int32& collectionId) 在 Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.VisitShapedQuery(ShapedQueryExpression ShapedQueryExpression) 在 Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.VisitExtension(表达式扩展Expression) 在 Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.VisitExtension(表达式扩展Expression) 在 Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor[TResult](表达式查询) 在 Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](表达式查询,布尔异步) 在 Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](IDatabase 数据库、表达式查询、IModel 模型、布尔异步) 在 Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler。
标头接受:text/plain 接受编码:gzip、deflate、br 接受语言:en-US,en 连接:关闭 主机:localhost:44385 引用者:https://localhost:44385/swagger/index.html 用户代理: Mozilla/5.0(Windows NT 10.0;Win64;x64)AppleWebKit/537.36(KHTML、 像 Gecko)Chrome/118.0.0.0 Safari/537.36 sec-ch-ua: "Chromium";v="118", "Brave";v="118", "Not=A?Brand";v="99" sec-ch-ua-mobile:?0 sec-ch-ua-platform:“Windows” sec-gpc:1 sec-fetch-site:同源 sec-fetch-mode:cors sec-fetch-dest:空
这是我在
repository
中的方法:
public class AnalyticsRepository : IAnalyticsRepository
{
public AnalyticsRepository(GuacamoleContext context)
{
Context = context;
}
public async Task<List<AnalyticsOrder>> GetOrderListAsync(string externalUID)
{
try
{
var OrderList = await Context.AnalyticsOrders.FromSqlInterpolated($"EXEC usp__OrderList @externalUID = {externalUID}").ToListAsync();
return OrderList;
}
catch (Exception e)
{
Console.WriteLine($"Error {e.Message}");
return new List<AnalyticsOrder>();
}
}
public GuacamoleContext Context { get; }
}
这是我在
service
中的方法:
public class SupplierAnalyticsService : ISupplierAnalyticsService
{
private readonly ISupplierAnalyticsRepository _supplierAnalyticsRepository;
public SupplierAnalyticsService(ISupplierAnalyticsRepository supplierAnalyticsRepository)
{
_supplierAnalyticsRepository = supplierAnalyticsRepository;
}
public async Task<List<AnalyticsOrder>> GetOrdersListAsync(string externalUID)
{
return await _supplierAnalyticsRepository.GetOrderListAsync(externalUID);
}
}
这是我的
controller
:
public class OrdersListController : ControllerBase
{
private readonly ISupplierAnalyticsService _supplierAnalyticsService;
public OrdersListController(ISupplierAnalyticsService supplierAnalyticsService)
{
_supplierAnalyticsService = supplierAnalyticsService;
}
[HttpGet("analytics/orders/list")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status413PayloadTooLarge)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<ActionResult<List<AnalyticsOrder>>> GetOrdersListAsync(string externalUID)
{
var list = await _supplierAnalyticsService.GetOrdersListAsync(externalUID);
return Ok(list);
}
在 DbContext 中,我添加了一个新实体,并将其设置为没有密钥(按照 Microsoft 文档此处:
)modelBuilder.Entity<AnalyticsOrder>().HasNoKey().ToView(null);
我在这里缺少什么?为什么通过 Swagger 执行
stored procedure
时会得到一个空数组?谢谢
Sooo,过了一段时间,找到了解决方案。
最初,我在
DbContext
中设置实体,如下所示:
modelBuilder.Entity<Type>().HasNoKey().ToView(null);
这里出了什么问题?没什么,除非你想将它映射到
view
。要将 entity
映射到 stored procedure
,您需要使用 .HasNoKey().ToFunction("[dbo].[YourStoredProcedureName]
。
更进一步,
EF Core
在每次迁移时都会创建一个表,尽管我特意将其设置为没有键。为了绕过它,我将其设置为从迁移中排除。完整的代码行是:
modelBuilder.Entity<YourType>().HasNoKey().ToFunction("[dbo].[YourStoredProcedureName]").Metadata.SetIsTableExcludedFromMigrations(true);
最后但并非最不重要的一点是,返回类型必须具有类道具而不是类字段。因此,在定义模型时,您会得到类似的内容:
public class Model
{
public int code { get; set; }
public string title { get; set; }
....................................
}
为了确保
EF Core
完全理解,我确保包含 stored procedure
的完全限定名称:
public async Task<List<Type>> GetListAsync(string externalUID)
{
try
{
var xList = await Context.DbSetType
.FromSqlInterpolated($"EXEC [dbo].[YourStoredProcedureName] @externalUID = {externalUID}")
.ToListAsync();
return xList;
}
catch (Exception e)
{
Console.WriteLine($"Error {e.Message}");
return new List<Type>();
}
}
我希望读者这个解决方案能够为您节省大量时间!