我正在解析XML(LINQ to XML),并且我在元素/属性为空的情况下使用可空类型(int?
和decimal?
)。但是,在构建我的集合以传递给DB(使用TVP)时,我不知道如何处理值实际为null的情况。我无法将null传递给SqlDataRecord SetInt32或SetDecimal,我不想设置为零....我实际上希望它为null。
告诉我int
没有超载?
以下计数是可以为空的类型(int?
计数)
SqlDataRecord rec = new SqlDataRecord(
new SqlMetaData("Name", SqlDbType.VarChar, 50),
new SqlMetaData("Type", SqlDbType.VarChar, 50),
new SqlMetaData("Count", SqlDbType.Int));
rec.SetString(0, dm.Name);
rec.SetString(1, dm.Type);
rec.SetString(2, dm.Count);
任何想法如何处理这个而不传递零(保持null)?
答案 0 :(得分:12)
扩展方法:
static class SqlDataRecordExtensions
{
static void SetNullableInt32(this SqlDataRecord rec, int index, Int32? value)
{
if (value.HasValue)
rec.SetInt32(index, value.GetValueOrDefault());
else
rec.SetDBNull(index);
}
}
或者,按照D Stanley的建议使用SetSqlInt32
:
static class SqlDataRecordExtensions
{
static void SetNullableInt32(this SqlDataRecord rec, int index, Int32? value)
{
rec.SetSqlInt32(index, value.HasValue ? value.GetValueOrDefault() : SqlInt32.Null);
// ^^^^^^^^^^^^^^^^^^^^^^^^^
// You can leave out the cast to (SqlInt32),
// because the conversion is implicit
}
}
请注意,2013年12月9日:由于评论而回到这个答案,我注意到一个很小的改进机会,基于Eric Lippert关于可以为空的微优化的系列,可以在http://ericlippert.com/2012/12/20/nullable-micro-optimizations-part-one/找到。
简而言之,虽然Value
属性需要较少的输入,因此对于程序员而言可能更为理想,但如果HasValue为false,则必须抛出异常。另一方面,GetValueOrDefault()
方法是一种简单的字段访问。因此,GetValueOrDefault()
需要更少的指令并且更有可能被内联,因此对于编译器和处理器来说它更为理想。
答案 1 :(得分:3)
我从未使用SqlDataRecord
,但在使用DataTable
和DataRow
时,或使用参数化查询时,我使用DBNull.Value
指定null
。
使用SqlDataRecord
,您似乎可以使用SetDBNull
方法。
答案 2 :(得分:0)
应使用SetSqlInt32
代替SetString
。尝试
rec.SetSqlInt32(2, (dm.Count.HasValue ? new SqlInt32(dm.Count) : SqlInt32.Null) );
答案 3 :(得分:0)
//在检查或处理可空类型时,我发现这对我来说是最好的 //在我的例子中,我正在检查存储在String []数组
中的值sqlcmdUpdateRecord.Parameters.AddWithValue("@strSomeValue", (strRecord[(int)
DataFields.SomeDataField] as object) ?? DBNull.Value);
答案 4 :(得分:0)
也许您可以尝试以下方法。
if(dm.Count == null){
rec.SetDBNull(2)
}
else{
rec.SetString(2, dm.Count);
}
答案 5 :(得分:0)
按照@phoog的建议,针对不同类型的扩展方法:
public static class ExtensionSqlDataRecord
{
public static void SetDateTime(this SqlDataRecord record, int ordinal, DateTime? value)
{
if (value != null)
{
record.SetDateTime(ordinal, (DateTime)value);
}
else
{
record.SetDBNull(ordinal);
}
}
public static void SetInt32(this SqlDataRecord record, int ordinal, int? value)
{
if (value != null)
{
record.SetInt32(ordinal, (int)value);
}
else
{
record.SetDBNull(ordinal);
}
}
public static void SetByte(this SqlDataRecord record, int ordinal, byte? value)
{
if (value != null)
{
record.SetByte(ordinal, (byte)value);
}
else
{
record.SetDBNull(ordinal);
}
}
public static void SetDecimal(this SqlDataRecord record, int ordinal, decimal? value)
{
if (value != null)
{
record.SetDecimal(ordinal, (decimal)value);
}
else
{
record.SetDBNull(ordinal);
}
}
public static void SetBoolean(this SqlDataRecord record, int ordinal, bool? value)
{
if (value != null)
{
record.SetBoolean(ordinal, (bool)value);
}
else
{
record.SetDBNull(ordinal);
}
}
}