如何将[TYPE]转换为可空<;[类型]>;在C#中?
问题: 我编写了一个方法,将SQL结果检索为类的列表,而不是数据表。 问题是,数据库中有一个int字段,可以为null 如果我用如何将[TYPE]转换为可空<;[类型]>;在C#中?,c#,.net,reflection,nullable,activator,C#,.net,Reflection,Nullable,Activator,问题: 我编写了一个方法,将SQL结果检索为类的列表,而不是数据表。 问题是,数据库中有一个int字段,可以为null 如果我用NULLint点击一行,DataReader返回DbNull.Value,而不是NULL。 因此System.Convert.ChangeType(objVal,fi.FieldType)抛出异常,因为它无法将DbNull转换为int 到目前为止还很糟糕。 当我将objVal与DbNull.Value进行比较时,我认为我已经解决了这个问题,如果是真的,则改为: Syst
NULL
int
点击一行,DataReader
返回DbNull.Value
,而不是NULL。
因此System.Convert.ChangeType(objVal,fi.FieldType)
抛出异常,因为它无法将DbNull
转换为int
到目前为止还很糟糕。
当我将objVal
与DbNull.Value
进行比较时,我认为我已经解决了这个问题,如果是真的,则改为:
System.Convert.ChangeType(null,fi.FieldType)
不幸的是,我刚刚意识到,结果的整数类型是0而不是NULL
因此,我刚刚尝试将类中的int类型更改为Nullable
,但现在我遇到了一个问题,即当值不是DbNull.value
时,ChangeType
抛出异常,因为它无法将int
转换为Nullable
因此,现在我尝试检测datareader
返回的对象类型,并将其转换为可为空的值
tTypeForNullable
正确显示为Nullable
。
但是当我查看结果类型时,我得到:int
为什么呢?更重要的是:我如何才能正确地做到这一点
请注意,因为type是一个对象,所以我不能使用泛型方法来创建Nullable
bool bisnull = IsNullable(objVal);
bool bisnullt = IsNullable(fi.FieldType);
if (bisnullt)
{
Type tTypeForNullable = typeof(Nullable<>).MakeGenericType(objVal.GetType());
//object result = Activator.CreateInstance(tTypeForNullable, new object[] { objVal });
//object result = Activator.CreateInstance(typeof(Nullable<int>), new object[] { objVal });
object result = Activator.CreateInstance(tTypeForNullable, objVal);
Type tres = result.GetType();
fi.SetValue(tThisValue, System.Convert.ChangeType(result, fi.FieldType));
}
请注意,因为类型是一个对象,所以我不能使用泛型方法来创建要装箱的
Nullable
可空值类型的装箱操作的结果永远不会是该类型的装箱值。它是null或不可为null的值类型。有关更多信息,请参阅。您见过实体框架吗?@Bas:是的,速度太慢了。但比反射快得多,如果你使用AsNoTracking,它的速度几乎和DataReader一样快。我刚刚遇到了同样的问题,我认为在c#中不可能使用反射来设置可为null类型的值。@Quandary:老实说,现在还不清楚你想做什么。是否存在“通过反射设置可为空的字段”的问题?将其与数据库方面等隔离是值得的。真正的问题是System.Convert.ChangeType不适用于可为空的类型。但我刚刚看到int的原始字段实际上是一个varchar。。。这就是为什么皈依是必要的。现在使用nullable,一切正常,如果fi.FieldType是nullable,我可能不会调用convert。@Quandary:我认为这不是你真正的核心问题-你不需要解决这个问题,你需要解决用反射设置字段的问题,对吗?如果ChangeType
为空时对您没有帮助,请不要使用它。@John Skeet:没有ChangeType,您无法直接将varchar读入int字段,这有点小意思。对于ChangeType,它将NULL映射为0。其思想过程是,使用NULL-able,Convert将NULL设置为NULL。现在我明白了为什么不能这样做了:Convert不能将可为null的类型作为对象返回,因为这将从返回的类型中删除可为null的类型。。。剩下的唯一问题是:这种对象装箱行为有什么意义……这使得不可能对可空类型进行任何转换。也许您应该将您的响应更新为:“这无法完成”@Quandary-只需将整数值存储到可为空的整数变量中即可。
bool bisnull = IsNullable(objVal);
bool bisnullt = IsNullable(fi.FieldType);
if (bisnullt)
{
Type tTypeForNullable = typeof(Nullable<>).MakeGenericType(objVal.GetType());
//object result = Activator.CreateInstance(tTypeForNullable, new object[] { objVal });
//object result = Activator.CreateInstance(typeof(Nullable<int>), new object[] { objVal });
object result = Activator.CreateInstance(tTypeForNullable, objVal);
Type tres = result.GetType();
fi.SetValue(tThisValue, System.Convert.ChangeType(result, fi.FieldType));
}
public System.Data.IDataReader ExecuteReader(System.Data.IDbCommand cmd)
{
System.Data.IDataReader idr = null;
lock(cmd)
{
System.Data.IDbConnection idbc = GetConnection();
cmd.Connection = idbc;
if (cmd.Connection.State != System.Data.ConnectionState.Open)
cmd.Connection.Open();
idr = cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection);
} // End Lock cmd
return idr;
} // End Function ExecuteReader