泛型参数的可为空的 return 值
Nullable return value on a generic argument
我正在尝试使用 Dapper 将模型保存到数据库中。我使用 input/output 参数设置参数,该参数是一个 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);
当我评估参数时,我在上面看到了我的 input/output 参数。
然而,当我尝试在我的存档中执行这一行时:
TKey returnedId = parameters.Get<TKey>(key.ResolvedName);
我遇到以下异常:
Exception:Caught: "Attempting to cast a DBNull to a non nullable type! Note that out/return parameters will not have updated values until the data stream completes (after the 'foreach' for Query(..., buffered: false), or after the GridReader has been disposed for QueryMultiple)" (System.ApplicationException)
A System.ApplicationException was caught: "Attempting to cast a DBNull to a non nullable type! Note that out/return parameters will not have updated values until the data stream completes (after the 'foreach' for Query(..., buffered: false), or after the GridReader has been disposed for QueryMultiple)"
Time: 7/21/2015 10:19:48 PM
Thread:[7200]
我假设这是一个问题,因为泛型类型在这种情况下不能为空,因为它是一个整数。这是因为 Dapper 总是 returns 可以为空吗?我刚刚暂时为存储过程的 OUTPUT 分配了一个常量值,以确保为输出分配了一些东西。
我如何解决返回 nullable 的 dapper,我将 int?
作为通用类型传递是唯一的解决方法吗?
更新
我能够使用这种方法解决它。所以不会让我 post 它作为答案。时间到了,我会post回答,除非其他人有更好的想法。
object returnedId = parameters.Get<TKey>(key.ResolvedName);
if (returnedId == null)
{
return default(TKey);
}
return (TKey)returnedId;
如果 DBNull 是一个有效值并且应该表示除 default(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);
return 类型的 SaveAsync 将反映键可能为空。如果键永远不应该为 null,并且如果 DBNull 应该默认为 default(TKey),则只需使用以下内容:
public async Task<TKey?> SaveAsync<TKey>(IGraph builder, IDataContext context = null) where TKey : struct
{
...
return parameters.Get<TKey?>(key.ResolvedName).GetValueOrDefault();
}
如果参数添加的方向为 inputoutput
(这就是上面的内容),我会收到此错误。如果方向是输入或输出,它都可以正常工作。
我这样解决了这个问题:
param.add(..., direction: MyVariable.hasValue ? ParameterDirection.Input : ParameterDirection.Ouput
)
但似乎 param.Get 应该适用于 inputoutput
参数。
我正在尝试使用 Dapper 将模型保存到数据库中。我使用 input/output 参数设置参数,该参数是一个 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);
当我评估参数时,我在上面看到了我的 input/output 参数。
然而,当我尝试在我的存档中执行这一行时:
TKey returnedId = parameters.Get<TKey>(key.ResolvedName);
我遇到以下异常:
Exception:Caught: "Attempting to cast a DBNull to a non nullable type! Note that out/return parameters will not have updated values until the data stream completes (after the 'foreach' for Query(..., buffered: false), or after the GridReader has been disposed for QueryMultiple)" (System.ApplicationException) A System.ApplicationException was caught: "Attempting to cast a DBNull to a non nullable type! Note that out/return parameters will not have updated values until the data stream completes (after the 'foreach' for Query(..., buffered: false), or after the GridReader has been disposed for QueryMultiple)" Time: 7/21/2015 10:19:48 PM Thread:[7200]
我假设这是一个问题,因为泛型类型在这种情况下不能为空,因为它是一个整数。这是因为 Dapper 总是 returns 可以为空吗?我刚刚暂时为存储过程的 OUTPUT 分配了一个常量值,以确保为输出分配了一些东西。
我如何解决返回 nullable 的 dapper,我将 int?
作为通用类型传递是唯一的解决方法吗?
更新
我能够使用这种方法解决它。所以不会让我 post 它作为答案。时间到了,我会post回答,除非其他人有更好的想法。
object returnedId = parameters.Get<TKey>(key.ResolvedName);
if (returnedId == null)
{
return default(TKey);
}
return (TKey)returnedId;
如果 DBNull 是一个有效值并且应该表示除 default(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);
return 类型的 SaveAsync 将反映键可能为空。如果键永远不应该为 null,并且如果 DBNull 应该默认为 default(TKey),则只需使用以下内容:
public async Task<TKey?> SaveAsync<TKey>(IGraph builder, IDataContext context = null) where TKey : struct
{
...
return parameters.Get<TKey?>(key.ResolvedName).GetValueOrDefault();
}
如果参数添加的方向为 inputoutput
(这就是上面的内容),我会收到此错误。如果方向是输入或输出,它都可以正常工作。
我这样解决了这个问题:
param.add(..., direction: MyVariable.hasValue ? ParameterDirection.Input : ParameterDirection.Ouput
)
但似乎 param.Get 应该适用于 inputoutput
参数。