Возвращаемые значения от Dapper.net запрос с хранимой процедурой
Я пытаюсь вызвать хранимую процедуру using Dapper.Net
и получить возвращаемые значения.
p.Add("@INCIDENT_ID", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue);
var retResults = con.Execute("usp_GetIncidentID", p, commandType:CommandType.StoredProcedure);
int IncidentID = p.Get<int>("INCIDENT_ID");
Я пробовал несколько разных вещей с направлением параметр и с помощью "@INCIDENT_ID"
. Если вы пройдете через результаты, вы увидите, что правильные возвращаемые значения снижаются в retResults
значение, но я не могу получить доступ к значениям так, как это описано в документации, как показано ниже..
Хранимые Процедуры Dapper поддерживает полностью сохраненные procs:
var user = cnn.Query<User>("spGetUser", new {Id = 1},
commandType: CommandType.StoredProcedure).First();}}}
If you want something more fancy, you can do:
var p = new DynamicParameters();
p.Add("@a", 11);
p.Add("@b", dbType: DbType.Int32, direction: ParameterDirection.Output);
p.Add("@c", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue);
cnn.Execute("spMagicProc", p, commandType: commandType.StoredProcedure);
int b = p.Get<int>("@b");
int c = p.Get<int>("@c");
6 ответов
вы можете прочитать значение, как показано ниже
var incidentId = retResults.ToList()[0].INCIDENT_ID;
Я подозреваемый (непроверено), что это чисто несоответствие в том, как вы называете параметр; попробуйте (обратите внимание на удаленное @
):
p.Add("INCIDENT_ID", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue);
var retResults = con.Execute("usp_GetIncidentID", p, commandType:CommandType.StoredProcedure);
int IncidentID = p.Get<int>("INCIDENT_ID");
я столкнулся с аналогичной проблемой, читая результаты QueryMultiple. Первый вызов Read () вернул правильный тип, второй-DapperRow. Я обнаружил, что используя типизированную версию Read ():
var lineExists = query.Read<int?>().FirstOrDefault() == 1;
решить мою проблему.
я сократил это для простоты. Я использую выходные параметры, потому что это дает мне полный контроль над типом данных, который передается обратно. Я мог бы использовать этот подход с любым другим сценарием, а не только вставками.
Сохраненный Proc:
ALTER PROCEDURE User_Insert (
@EmailAddress nvarchar(255),
@Id bigint OUT
) AS
INSERT INTO User (
[EmailAddress]
) VALUES (
@EmailAddress
)
set @Id = SCOPE_IDENTITY()
Код Respository:
var sql = "Execute User_Insert @EmailAddress, @Id = @Id OUTPUT";
var _params = new DynamicParameters();
_params.Add("EmailAddress", user.EmailAddress);
_params.Add("Id", dbType: DbType.Int64, direction: ParameterDirection.Output);
using (var connection = new SqlConnection(ConnectionString)) {
connection.Open();
using (var transaction = connection.BeginTransaction()) {
var result = SqlMapper.Execute(connection, sql, param, transaction);
transaction.Commit();
}
}
var id = _params.Get<long>("Id");
используя тестовую версию Dapper, я обнаружил, что это работает как шарм:
result = dbConnection.ExecuteScalar<int>(typeof(UCCCCException).Name + "_c",
obj, commandType: CommandType.StoredProcedure);
Я пишу общий для использования при вставке объектов любого типа в базу данных.
хранимая процедура выглядит так:
ALTER PROCEDURE [dbo].[UCCCCException_c]
(
@Id int = null,
@ExceptionDate datetime = null,
@HResult int = 0,
@Message varchar(8000) = null,
@Source varchar(8000) = null,
@StackTrace varchar(8000) = null,
@Module varchar(8000) = null,
@Name varchar(8000) = null,
@created_at datetime = null,
@updated_at datetime = null,
@created_by int = null,
@updated_by int = null
,
@Creator varchar(255) = null,
@Updator varchar(255) = null
)
AS
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
Insert into dbo.uccccexceptions ( ExceptionDate, HResult, [Message], [Source], StackTrace, Module, Name)
values (
coalesce(@ExceptionDate,getdate()),
@HResult,
@Message,
@Source,
@StackTrace,
@Module,
@Name
)
;
select @@Identity;
go
предостережения по этому, что вы должны указать запись для каждого свойства в классе, который вы используете, даже если эти свойства не существуют в целевой таблице, в качестве параметра для хранимой процедуры. Это может раздражать, если вы имейте несколько полей, которые являются полями просмотра в ситуациях MVC.
чтобы получить возвращаемое значение, вам просто нужно использовать Execute и убедиться, что ваш последний оператор Select @@Identity в хранимой процедуре.
он отлично работает и позволяет мне написать общую команду insert в моем репозитории следующим образом:
public virtual int Insert(T obj)
{
int result = -2;
if (!databaseOnline)
{
throw new Exception(HttpStatusCode.ServiceUnavailable.ToString());
}
if (obj != null)
{
try
{
using (IDbConnection dbConnection = ConnectionProvider.OpenConnection())
{
dbConnection.Open();
result = dbConnection.ExecuteScalar<int>(typeof(T).Name + "_c",
obj, commandType: CommandType.StoredProcedure);
}
}
catch (SqlException sqlex)
{
Logger.LogError(sqlex, false);
throw;
}
catch (Exception ex)
{
Logger.LogError(ex);
throw;
}
}
return result;
}
Я использую соглашение в моей базе данных, что имя хранимой процедуры - это имя типа, за которым следует " _s "для select," _c "для insert," _d" "удалить" и "Макс" для обновления.
PS: Я ненавижу использовать DynamicParameters Dapper или любое другое устройство, которое требует использования другого метода вставки или обновления для каждого из ваших классов в общем репозитории.
решение динамические параметры не чисто. Гораздо лучше сделать код хранимой процедуры возвращающим целое число (выберите 1;) и использовать dapper ExecuteScalar<int>("[sp_name]", params);