我正在尝试使用Dapper将模型保存到数据库中。我使用输入/输出参数设置参数,该参数是int
,其中包含用于更新的现有主键值。
public async Task<TKey> SaveAsync<TKey>(IGraph builder, IDataContext context = null)
{
var parameters = this.GetParametersFromDefinition(builder, DefinitionDirection.In);
// See if we have a key defined. If not, we assume this is a new insert.
// Otherwise we pull the key out and assume it's an update.
PropertyDefinition key = builder.GetKey();
if (key != null)
{
parameters.Add(key.ResolvedName, key.PropertyValue, null, ParameterDirection.InputOutput);
}
else
{
throw new InvalidOperationException("The data graph did not have a primary key defined for it.");
}
await this.ExecuteProcedure(parameters, builder, context);
object returnedId = parameters.Get<TKey>(key.ResolvedName);
return returnedId == null ? default(TKey) : (TKey)returnedId;
}
private Task ExecuteProcedure(DynamicParameters parameters, IGraph builder, IDataContext context = null)
{
ProcedureDefinition mapping = builder.GetProcedureForOperation(ProcedureOperationType.Insert);
if (string.IsNullOrEmpty(mapping.StoredProcedure))
{
throw new InvalidOperationException("No stored procedure mapped to the builder.");
}
// Query the database
return this.SetupConnection(
context,
(connection, transaction) => connection.ExecuteAsync(
mapping.StoredProcedure,
parameters,
commandType: CommandType.StoredProcedure,
transaction: transaction));
}
它是这样调用的:
this.Address.AddressId = await repository.SaveAsync<int>(graph);
当我评估参数时,我会看到输入/输出参数。
但是当我尝试在保存中执行此行时:
TKey returnedId = parameters.Get<TKey>(key.ResolvedName);
我获得以下例外:
例外:Caught:&#34;尝试将DBNull强制转换为非可空类型!请注意,out / return参数在数据流完成之前没有更新的值(在查询(...,缓冲:false)之后,或者在为QueryMultiple处理了GridReader之后)&& 39; #34; (System.ApplicationException) 捕获到System.ApplicationException:&#34;尝试将DBNull强制转换为非可空类型!请注意,out / return参数在数据流完成之前没有更新的值(在查询(...,缓冲:false)之后,或者在为QueryMultiple处理了GridReader之后)&& 39; #34; 时间:2015/7/21 10:19:48 PM 螺纹:[7200]
我假设这是泛型类型在这种情况下不可为空的问题,因为它是一个整数。这是因为Dapper总是返回一个可空的?我现在只是在存储过程中为OUTPUT指定了一个常量值,以确保为输出分配了一些东西。
我如何解决dapper返回一个可空的问题,是唯一的方法我将int?
作为泛型类型传递给它?
我能够使用这种方法解决它。所以我不会发布它作为答案。当时间限制到期时,我会发布一个答案,除非其他人有更好的想法。
object returnedId = parameters.Get<TKey>(key.ResolvedName);
if (returnedId == null)
{
return default(TKey);
}
return (TKey)returnedId;
答案 0 :(得分:1)
如果DBNull是一个有效值,并且应该表示默认值以外的东西(TKey)(例如:default(int)= 0),并且如果TKey将始终是值类型,则将TKey约束为结构,如下所示:
public async Task<TKey?> SaveAsync<TKey>(IGraph builder, IDataContext context = null) where TKey : struct
{
...
}
然后像这样得到钥匙:
TKey? returnedId = parameters.Get<TKey?>(key.ResolvedName);
SaveAsync的返回类型将反映该键可以为null。如果密钥永远不应为null,并且DBNull应默认为默认值(TKey),则只需使用以下内容:
public async Task<TKey?> SaveAsync<TKey>(IGraph builder, IDataContext context = null) where TKey : struct
{
...
return parameters.Get<TKey?>(key.ResolvedName).GetValueOrDefault();
}