简体   繁体   English

如何 map 来自 postresql 中的存储过程的结果集,我使用 Entity Framework Core 返回多个游标

[英]How to map set of results from stored procedure in postresql where I return multiple cursors using Entity Framework Core

I was working on stored procedure to get some statistics from database, but I do not want to do it in code side because there is lots of data to process and there are some tables I would need to call after execution, well lots of stuff that will use resources and can be made cheaply by database query.我正在处理存储过程以从数据库中获取一些统计信息,但我不想在代码端执行它,因为有很多数据要处理,并且有一些表我需要在执行后调用,还有很多东西将使用资源并且可以通过数据库查询廉价地制作。 So I came up with stored procedure that looks like:所以我想出了看起来像这样的存储过程:

CREATE OR REPLACE FUNCTION PUBLIC.get_statistics_info(severityref refcursor, eventsref refcursor) 
    RETURNS SETOF refcursor 
    LANGUAGE 'plpgsql'
AS $BODY$ 
                                
BEGIN
    OPEN severityref FOR 
        SELECT 
            si."VarId", si."Date", si."SystemId", si."SystemName", 
            SUM(ss."InfoCounter") AS info, SUM(ss."WarningCounter") AS warn, SUM(ss."NonFatalCounter") AS nfatal, SUM(ss."FatalCounter") AS fatal,
            SUM(ssm."InfoCounter") AS minfo, SUM(ssm."WarningCounter") AS mwarn, SUM(ssm."NonFatalCounter") AS nfatal, SUM(ssm."FatalCounter") AS mfatal
        FROM "StatisticsInfo" AS si
        left JOIN "StatisticsSeverity" AS ss ON si."Id" = ss."StatisticsInfoId"
        left JOIN "StatisticsSeverityMaintenance" AS ssm ON si."Id" = ssm."StatisticsInfoId"
        GROUP BY si."VarId", si."Date", si."SystemId", si."SystemName"; 
    RETURN NEXT severityref;                                                                            

    OPEN eventsref for 
        SELECT 
            si."VarId", si."SystemId" ,
            se."EventId" AS eventid, se."Counter" AS eventcounter, sed."Symbol" AS eventsymbol,
            sem."EventId" AS mseventid, sem."Counter" AS mseventcounter, msed."Symbol" AS meventsymbol
        FROM "StatisticsInfo" AS si
        left JOIN "StatisticsEvent" AS se ON si."Id" = se."StatisticsInfoId"
        LEFT JOIN "EventDefinitions" AS sed ON se."EventId" = sed."Decimal"
        left JOIN "StatisticsEventMaintenance" AS sem ON si."Id" = sem."StatisticsInfoId"
        LEFT JOIN "EventDefinitions" AS msed ON sem."EventId" = msed."Decimal";  
    RETURN NEXT eventsref;   
END
$BODY$;

It sums up statistics using 2 cursors, so I should get 2 sets of data as a result.它使用 2 个游标汇总统计信息,因此我应该得到 2 组数据作为结果。 But now I have a problem how to recevie it.但是现在我有一个问题如何接收它。 I am using entity framework core for my db operations, so I made something like this.我正在为我的数据库操作使用实体框架核心,所以我做了这样的事情。

Service Call:服务电话:

    public async ValueTask<IEnumerable<object>> GetCombinedStatisticsInfo()
    {
        try
        {
            using var unitOfWork = UnitOfWorkFactory.CreateGeneralContext();

            //I MADE THIS MAPPING AS TEST TO CHECK WHAT WILL BE RETURNED
            var map = new Func<DbDataReader, object>(reader => new
            {
                first = reader[0]
            });

            const string procedureCall = "BEGIN; SELECT get_statistics_info('severity', 'events'); FETCH ALL IN \"severity\"; FETCH ALL IN \"events\"; COMMIT;";
            var result = await unitOfWork.GeneralRepository.ExecuteSqQuery(procedureCall, map);
            unitOfWork.Dispose();
            return result;
        }
        catch (Exception ex)
        {
            logger.Error(ex);
            throw;
        }
    }

Repository:存储库:

    public async ValueTask<IEnumerable<TResponse>> ExecuteSqlProcedure<TResponse>(string procedureCall, Func<DbDataReader, TResponse> map)
    {
        var transaction = await this.Context.Database.BeginTransactionAsync();
        var result = await ExecuteSql(procedureCall, map, CommandType.StoredProcedure);
        await transaction.CommitAsync();
        return result;
    }

    private async ValueTask<IEnumerable<TResponse>> ExecuteSql<TResponse>(string query, Func<DbDataReader, TResponse> map, CommandType commandType)
    {
        await using var command = this.Context.Database.GetDbConnection().CreateCommand();
        command.CommandText = query;
        command.CommandType = commandType;

        await this.Context.Database.OpenConnectionAsync();
        await using var result = await command.ExecuteReaderAsync();
        var entities = new List<TResponse>();

        while (await result.ReadAsync())
        {
            entities.Add(map(result));
        }

        return entities;
    }

Well basically it executes procedure but as a result I am getting cursor names like: {first: "severity";好吧,基本上它执行程序,但结果我得到 cursor 名称,如:{first: "severity"; first: "events"}, so I checked execution on my database and it works i get 2 sets of data using that transaction with fetch.首先:“事件”},所以我检查了我的数据库上的执行情况,它可以工作,我使用该事务获取 2 组数据。 So my question is what am I doing wrong here?所以我的问题是我在这里做错了什么?

So I figured this one out I need to add each fetch in a transaction after executing stored procedure separately and map results, something like:所以我发现我需要在单独执行存储过程和 map 结果之后在事务中添加每个提取,例如:

    public async ValueTask<Dictionary<string, List<object>>> ExecuteGetStatisticsProcedure()
    {
        var transaction = await this.Context.Database.BeginTransactionAsync();
        var entities = new Dictionary<string, List<object>>
        {
            {SeverityKey, new List<object>() },
            {EventsKey, new List<object>() }
        };

        try
        {
            async Task GetSeverity(DbCommand severityCommand)
            {
                const string fetchSeverityCursor = "FETCH ALL IN \"severity\";";
                severityCommand.CommandText = fetchSeverityCursor;
                await using var result = await severityCommand.ExecuteReaderAsync();
                while (await result.ReadAsync())
                {
                    entities[SeverityKey].Add(
                        new
                        {
                            //Map results
                        });
                }
            }

            async Task GetEvents(DbCommand eventsCommand)
            {
                const string fetchEventCursor = "FETCH ALL IN \"events\";";
                eventsCommand.CommandText = fetchEventCursor;

                await eventsCommand.ExecuteReaderAsync();
                await using var eventsResult = await eventsCommand.ExecuteReaderAsync();
                while (await eventsResult.ReadAsync())
                {
                    entities[EventsKey].Add(
                        new
                        {
                            //Map results
                        });
                }
            }

            await using var command = this.Context.Database.GetDbConnection().CreateCommand();
            command.CommandType = CommandType.Text;
            await this.Context.Database.OpenConnectionAsync();

            const string procedureCallProcedure = "SELECT * From get_statistics_info(\'severity\', \'events\');";
            await this.Context.Database.ExecuteSqlRawAsync(procedureCallProcedure);

            await GetSeverity(command);
            await GetEvents(command);

            await transaction.CommitAsync();
        }
        catch (Exception ex)
        {
            Logger.Error(ex);
            await transaction.RollbackAsync();
        }

        return entities;
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用 FromSqlRaw Entity Framework Core 3.1 从存储过程返回多个 SELECT 集 - How to return multiple SELECT sets from a stored procedure using FromSqlRaw Entity Framework Core 3.1 Entity Framework Core 使用存储过程删除带有 bool 返回值的实体 - Entity Framework Core using stored procedure to delete entity with bool return Entity Framework Core 3.1 从存储过程返回值 (int) - Entity Framework Core 3.1 Return value (int) from stored procedure 是否有任何可能的方法来返回通过使用 .net Core MVC 中的 Entity Framework Core 的存储过程生成的结果..? - Is there any possible ways to return the results generated through a stored procedure using Entity Framework Core in .net Core MVC..? 如何在 Entity Framework Core 中的多个表上使用联接调用存储过程? - How to call Stored Procedure with join on multiple tables in Entity Framework Core? 不使用实体框架时如何将存储过程结果返回到类列表中? - How to return stored procedure results into a List of Class when not using entity framework? 如何使用Entity Framework 4访问存储过程的“结果”,“消息”和“返回值”? - How to access 'Results', 'Messages', and 'Return Value' of a Stored Procedure using Entity Framework 4? 如何使用Entity Framework加载存储过程的结果? - How can I use Entity Framework to load the results of a stored procedure? 如何在实体框架中检查存储过程的返回值 - how can i check return value of stored procedure in entity framework 在Entity Framework数据库优先方法中,如何从存储过程返回多个结果集? - In Entity Framework database-first approach how to return multiple result sets from a stored procedure?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM