Выполнить хранимую процедуру в EF Core, возвращающую int из JOIN. блейзер (на стороне клиента)

Как я могу получить значение int в EF Core, возвращенное из хранимой процедуры в SQL Server?

--Two tables, Employee and AspNetUsers--
CREATE PROCEDURE SP_GetIdEmployeeByUserName
     (@username varchar(100), @idemployee int output)
AS
BEGIN
    SELECT @idemployee = (SELECT e.Id 
                          FROM Employee e
                          JOIN AspNetUsers a ON e.IdUser = a.Id
                          WHERE a.Email = @username)

END

--Executing in database--
DECLARE @idemp INT;
EXEC SP_GetIdEmployeeByUserName '[email protected]', @idemp output
SELECT @idemp;

Возврат правильного Employee.Id в тестах SQL Server

idemp `Id = 40`

Теперь в контроллере Blazor (на стороне клиента) я пытаюсь выполнить хранимую процедуру.

[HttpGet]
[Route("getbyname")]
public int GetByName([FromQuery] string username)
{
        try
        {
            if (!string.IsNullOrEmpty(username))
            {
                SqlParameter paramUsername = new SqlParameter("@username", username);

                var paramOut = new SqlParameter
                {
                    ParameterName = "@idemp",
                    SqlDbType = System.Data.SqlDbType.Int,
                    Direction = System.Data.ParameterDirection.Output,
                };

                var result = _context
                    .Employee.FromSqlRaw
                    ($"EXEC SP_GetIdFuncByUserName @username, @idemp OUTPUT", paramUsername, paramOut)
                    .FirstOrDefault();

                Console.WriteLine("result = >>>>>>>>> " + result);

                return result.Id;
            }
            else
            {
                return 0;
            }

        }
        catch (Exception ex)
        {
            Console.WriteLine("ex -> " + ex);
            throw;
        }
    }

Я получаю это исключение:

FromSqlRaw или FromSqlInterpolated были вызваны с несоставным SQL и запросом, составляющим его.
Рассмотрите возможность вызова AsEnumerable после метода FromSqlRaw или FromSqlInterpolated для выполнения композиции на стороне клиента.

Если попробовать

var result = _context
                .Database.ExecuteSqlRaw
                ($"EXEC SP_GetIdFuncByUserName @username, @idemp OUTPUT", paramUsername, paramOut);

он всегда возвращает -1, потому что ни одна строка не была затронута.

Я много чего вижу, но безуспешно ... Заранее спасибо

_context.Database.ExecuteSqlCommand if obsolete

person Diego Venâncio    schedule 12.06.2020    source источник
comment
вы пробовали `FromSqlRaw?   -  person vivek nuna    schedule 12.06.2020
comment
Боковое примечание: вам не следует использовать префикс sp_ для ваших хранимых процедур. Microsoft зарезервировала этот префикс для собственного использования ( см. Именование хранимых процедур), и вы действительно рискуете столкнуться с конфликтом имен когда-нибудь в будущем. Это также плохо сказывается на производительности хранимых процедур. Лучше просто избегать sp_ и использовать что-то еще в качестве префикса - или вообще не использовать префикс!   -  person marc_s    schedule 12.06.2020


Ответы (1)


У вас некомпонованный SQL. Дело в том, что Entity Framework напишет что-то вроде

SELECT [Generated Column Names] FROM 
(
    @YOURQUERY
)

Это делается для определения формата, позволяющего материализовать (вложенные) результаты, постранично их и так далее.

Он не может составить этот запрос, если вы ничего не выберете из своей хранимой процедуры. В любом случае он не возвращает набор результатов, поэтому вы также не сможете выбрать из dbContext.Employee. Это будут два разных запроса. Один для получения идентификатора, который у вас уже был:

var result = _context
            .Database.ExecuteSqlRaw
            ($"EXEC SP_GetIdFuncByUserName @username, @count OUTPUT", paramUsername, paramOut);

Это действительно возвращает -1, потому что в вашем запросе есть ошибка. Вы предоставляете параметр с именем @count, но настроенный параметр с именем @idemp.

Поэтому убедитесь, что вы правильно передали параметр:

var result = _context
                .Database.ExecuteSqlRaw
                ($"EXEC SP_GetIdFuncByUserName @username, @idemp OUTPUT", paramUsername, paramOut);

Затем запросите, используя параметр ID:

var employeeId = paramOut.Value;
var employee = _context.Employee.FirstOrDefault(e => e.Id == employeeId);
person CodeCaster    schedule 12.06.2020
comment
Ты прав. @count был ошибкой только при копировании / вставке. paramOut.Value; спаси меня. - person Diego Venâncio; 12.06.2020