1datatable 创建可空类型 2 匿名类型创建可空 3 匿名类型设置为泛型(最简单的办法是定义一个类) 也可以反射在IL里面创建类 动态产生一个类型,并且动态写入 IL 代码产生属性。 比较复杂 DBNull与Null的区别
dataTable.Columns.Add("Dt", typeof(Nullable<DateTime>)); 会报错 DataSet 不支持 System.Nullable<>。
要用这个 dataTable.Columns.Add("Dt", typeof(Nullable<DateTime>).GetGenericArguments()[0]);
var entity = new { Name = "item", ID = 0, GuidType = Guid.Empty, Dt = (Nullable<DateTime>)DateTime.Now }; 这个
var entity2 = new { Name = "item", ID = 0, GuidType = Guid.Empty, Dt = DBNull.Value };
var entity3 = new { Name = "item", ID = 0, GuidType = Guid.Empty, Dt = (Nullable<DateTime>)null }; 这个
using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace ConsoleApplication24 { enum A { A, b, c, d, e, f } class Program { public static IList FromTable(Type GenericType, DataTable dataTable) { Type typeMaster = typeof(List<>); Type listType = typeMaster.MakeGenericType(GenericType); IList list = Activator.CreateInstance(listType) as IList; if (dataTable == null || dataTable.Rows.Count == 0) return list; var constructor = GenericType.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) .OrderBy(c => c.GetParameters().Length).First(); var parameters = constructor.GetParameters(); var values = new object[parameters.Length]; foreach (DataRow dr in dataTable.Rows) { int index = 0; foreach (ParameterInfo item in parameters) { object itemValue = null; if (dr[item.Name] != null && dr[item.Name] != DBNull.Value) { itemValue = Convert.ChangeType(dr[item.Name], item.ParameterType); } values[index++] = itemValue; } list.Add(constructor.Invoke(values)); } return list; } public delegate object[] CreateRowDelegate<T>(T t); //public static DataTable ToDataTable<T>(this IEnumerable<T> varlist, CreateRowDelegate<T> fn) //{ // DataTable dtReturn = new DataTable(); // // column names // PropertyInfo[] oProps = null; // // Could add a check to verify that there is an element 0 // foreach (T rec in varlist) // { // // Use reflection to get property names, to create table, Only first time, others will follow // if (oProps == null) // { // oProps = ((Type)rec.GetType()).GetProperties(); // foreach (PropertyInfo pi in oProps) // { // Type colType = pi.PropertyType; if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>))) // { // colType = colType.GetGenericArguments()[0]; // } // dtReturn.Columns.Add(new DataColumn(pi.Name, colType)); // } // } // DataRow dr = dtReturn.NewRow(); foreach (PropertyInfo pi in oProps) // { // dr[pi.Name] = pi.GetValue(rec, null) == null ? DBNull.Value : pi.GetValue(rec, null); // } // dtReturn.Rows.Add(dr); // } // return (dtReturn); //} static public object ChangeType(object value, Type type) { if (value == null && type.IsGenericType) return Activator.CreateInstance(type); if (value == null) return null; if (value == DBNull.Value) return null; if (type == value.GetType()) return value; if (type.IsEnum) { if (value is string) return Enum.Parse(type, value as string); else return Enum.ToObject(type, value); } if (!type.IsInterface && type.IsGenericType) { Type innerType = type.GetGenericArguments()[0]; object innerValue = ChangeType(value, innerType); return Activator.CreateInstance(type, new object[] { innerValue }); } if (value is string && type == typeof(Guid)) return new Guid(value as string); if (value is string && type == typeof(Version)) return new Version(value as string); if (!(value is IConvertible)) return value; return Convert.ChangeType(value, type); } public static List<T> GetEntities<T>(DataTable table) where T : new() { List<T> entities = new List<T>(); try { foreach (DataRow row in table.Rows) { T entity = new T(); foreach (var item in entity.GetType().GetProperties()) { if (table.Columns.Contains(item.Name)) item.SetValue(entity, ChangeType(row[item.Name], item.PropertyType), null); } entities.Add(entity); } } catch { } return entities; } static void Main(string[] args) { var entity = new { Name = "item", ID = 0, GuidType = Guid.Empty, Dt = (Nullable<DateTime>)DateTime.Now }; // 可空 var entity2 = new { Name = "item", ID = 0, GuidType = Guid.Empty, Dt = DBNull.Value }; // System.DBNull 类型 var entity3 = new { Name = "item", ID = 0, GuidType = Guid.Empty, Dt = (Nullable<DateTime>)null }; //// 可空 //var entity4 = new { Name = "item", ID = 0, GuidType = Guid.Empty, Dt = null }; //错误 1 不能将“<null>”赋值给匿名类型属性 DataTable dataTable = new DataTable(); dataTable.Columns.Add("Name", typeof(string)); dataTable.Columns.Add("ID", typeof(int)); dataTable.Columns.Add("GuidType", typeof(Guid)); //dataTable.Columns.Add("Dt", typeof(Nullable<DateTime>)); dataTable.Columns.Add("Dt", typeof(Nullable<DateTime>).GetGenericArguments()[0]); for (int i = 0; i < 10; i++) { DataRow dr = dataTable.NewRow(); dr["Name"] = "STRING" + i; dr["ID"] = i; if (i % 2 == 0) dr["GuidType"] = Guid.Empty; else { dr["GuidType"] = DBNull.Value; // dataTable 行列 里面数据 存的都是 object 类型的 所以可以 DBNull.Value 替代 可 null } if (i == 0) { dr["Dt"] = DateTime.Now; } else { //dr["Dt"] = null; //不能将 Column“Dt”设置为 null。请改用 DBNull。 DBNull 是 类 (DBNull类) 也属于object类型 dr["Dt"] = DBNull.Value; // null 为 空指针 空引用 不是类 } dataTable.Rows.Add(dr); } object op = DBNull.Value; object op2 = null; Console.WriteLine(op is object); Console.WriteLine(op2 is object); //IList list = FromTable(entity.GetType(), dataTable); //IList list = FromTable(entity.GetType(), dataTable); Type o = entity.GetType(); var list = GetEntities<As>(dataTable); Console.WriteLine(((A)1).ToString()); } } class As {// var entity = new { Name = "item", ID = 0, GuidType = Guid.Empty, Dt = (Nullable<DateTime>)DateTime.Now }; public string Name { get; set; } public int ID { get; set; } public Guid? GuidType { get; set; } public DateTime? Dt { get; set; } } }
DBNull与Null的区别
在其他网站上看见的,感觉讲的不错,链接地址:http://www.cnblogs.com/muou/archive/2010/03/23/1692391.html
Null是.net中无效的对象引用。
DBNull是一个类。DBNull.Value是它唯一的实例。它指数据库中数据为空(<NULL>)时,在.net中的值。
null表示一个对象的指向无效,即该对象为空对象。
DBNull.Value表示一个对象在数据库中的值为空,或者说未初始化,DBNull.Value对象是指向有效的对象。
DBNull在DotNet是单独的一个类型 System.DBNull 。它只有一个值 DBNull.Value 。DBNull 直接继承 Object ,所以 DBNull 不是 string , 不是 int , 也不是 DateTime 。。。
但是为什么 DBNull 可以表示数据库中的字符串,数字,或日期呢?原因是DotNet储存这些数据的类(DataRow等)都是以 object 的形式来储存数据的。
对于 DataRow , 它的 row[column] 返回的值永远不为 null , 要么就是具体的为column 的类型的值 。要么就是 DBNull 。 所以 row[column].ToString() 这个写法永远不会在ToString那里发生NullReferenceException,但有可能抛下标越界的异常。
DBNull 实现了 IConvertible 。 但是,除了 ToString 是正常的外,其他的ToXXX都会抛出不能转换的错误。
在 IDbCommand(OleDbCommand,SqlCommand...) 的ExecuteScalar的返回值中,情况可以这样分析:
select 1 这样返回的object是 1
select null 这样返回的是DBNull.Value
select isnull(null,1) 返回的是 1
select top 0 id from table1 这样返回的值是null
select isnull(id,0) from table1 where 1=0 返回的值是null
这里 ExecuteScalar 的规则就是,返回第一列,第一行的数据。如果一行都没有,那么ExecuteScalar就返回null。如果有第一行,但是第一列为空,那么返回的是 DBNull 。如果第一列第一行不为空,那么ExecuteScalar就直接对应的DotNet的值。
规则就是这样的。这里容易犯的一个错误是,把ExecuteScalar返回DBNull与null的情况混淆,例如:
string username=cmd.ExecuteScalar().ToString();
除非你认为cmd执行后,肯定至少有一行数据,否则这里就会出错。
又或者 select id from usertable where username=@name 这样的sql语句,如果找不到记录,那么ExecuteScalar则会返回null,所以千万不要
int userid=Convert.ToInt32(cmd.ExecuteScalar());
或者你会这样写 SQL 语句:select isnull(id,0) from usertable where username=@name
但是 int userid=Convert.ToInt32(cmd.ExecuteScalar()); 依然会出错,因为上面的语句不成立时,仍然是不返回任何行。
对于IDbDataParameter(OleDDbParameter,SqlParameter..)的Value,如果为null,则代表该参数没有指定,或者是代表DEFAULT。如果为DBNull.Value,则代表SQL中的NULL
所以,如果你要调用存储过程,里面有默认参数 @val nvarchar(20)="AABB" ,
那么cmd.Parameters["@val"].Value=null 代表使用这个默认的 "AABB"
而cmd.Parameters["@val"].Value=DBNull.Value 代表使用NULL来传给 @val
你可以用Convert.IsDBNull来判断一个值是否DBNull。注意Convert.IsDBNull(null)是false,也就是说null跟DBNull.Value是不等的。
C# DBNull和null说明
null 是.net中无效的对象引用。在数据类型中,对于引用类型的默认只就是为null,表示当前变量不指向任何对象。也称空指针。
DBNull是一个类。DBNull.Value是它唯一的实例。继承自Object
它用来对应数据库的数据为空(<NULL>)时,在.Net中的对应值。
object obj1 = DBNull.Value;
它不是数据类型,只是用来对应数据库中为null的值,表示“不知道”。
例如:数据库一列是int类型,可空,如果在读取数据库是对于DataRow,返回的数据null对应的结果就是DBNull.Value,
它的row[column]返回的值永远不会为null,所以row[column].ToString()这个写法不会抛出NullReferenceException的空指针异常。
接着说,如果想向数据库中的int列的值插入NULL的话,在指定数据库参数@id的时候,如果参数的值应该是DBNull.Value而不是null,如果是null则数据库抛出异常“@xxx 没有指定值”。
DBNull 实现了 IConvertible 。 但是,除了 ToString 是正常的外,其他的ToXXX都会抛出不能转换的错误。
在 IDbCommand(OleDbCommand,SqlCommand...) 的ExecuteScalar的返回值中,情况可以这样分析:
select 1 这样返回的object是 1
select null 这样返回的是DBNull.Value
select isnull(null,1) 返回的是 1
select top 0 id from table1 这样返回的值是null
select isnull(id,0) from table1 where 1=0 返回的值是null
这里 ExecuteScalar 的规则就是,返回第一列,第一行的数据。如果一行都没有,那么ExecuteScalar就返回null。如果有第一行,但是第一列为空,那么返回的是 DBNull 。如果第一列第一行不为空,那么ExecuteScalar就直接对应的DotNet的值。
你可以用Convert.IsDBNull来判断一个值是否DBNull。注意Convert.IsDBNull(null)是false,也就是说null跟DBNull.Value是不等的。
DBNull.Value,, 是适用于向数据库的表中插入空值。而 null,是指在程序中表示空引用。 或者对象为空。就是没有实例化。
row[column]的值为DBNull.Value的话,至少说明它是从数据库中取到值了,对应了数据库中的空值;但如果row[column]的值为null的话,说明没有从数据库中取到值。DBNull.Value是一个有着内存地址的具体类型的值,映射了数据库中的null值;而NULL则是空指向,不存在对应的内存地址。任何对象赋值为null后,内存就释放了。
---------------------
作者:beautifulsarah
来源:CSDN
原文:https://blog.csdn.net/beautifulsarah/article/details/54691670
版权声明:本文为博主原创文章,转载请附上博文链接!

浙公网安备 33010602011771号