针对 MSSQL 服务器执行存储过程时返回空数组

问题描述 投票:0回答:1

我正在尝试针对本地 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
时会得到一个空数组?谢谢

.net sql-server entity-framework .net-core
1个回答
0
投票

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>();
        }
}

我希望读者这个解决方案能够为您节省大量时间!

© www.soinside.com 2019 - 2024. All rights reserved.