版权声明:未经本人允许,必须声明原文转载地址和作者! https://blog.csdn.net/liuchang19950703/article/details/88050162
一:关于 DBNull和 Null 的区别
1.查询数据时:DBNull是C#查询数据库字段的NULL值的一个类型,该类型不能直接赋值给C#实体类的属性,会造成转换报错,因此需要转换成C#的NULL再进行赋值,
2.插入或者更新数据时:C#插入或者更改数据库字段时,C#的NULl也要转换成DBNull再对数据库进行操作,否则也会造成转换报错
注意:这里要注意实体类中的【DateTime】字段,该字段如果不赋值会默认是【0001/01/01 00:00L00】,数据库不能识别这个时间,会报转换错误,所以在实体类中的【DateTime】字段中间加上 "?".
附上代码:
1.查询数据:
/// <summary>
/// 获取所有对象
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public List<T> GetAllList<T>() where T : BaseModel
{
try
{
List<T> list = new List<T>();
Type type = typeof(T);
StringBuilder sql = new StringBuilder();
string colNameStr = string.Join(",", type.GetProperties().Select(a => string.Format("[{0}]", AttributeHelp.GetColNameByProp(a))));
sql.AppendFormat(" select {0} from {1} ", colNameStr, type.Name);
using (conn = new SqlConnection(_connStr))
{
SqlCommand cmd = new SqlCommand(sql.ToString(), conn);
conn.Open();
SqlDataReader reader = cmd.ExecuteReader();
list = GetListBySqlDataReader<T>(reader);
}
return list;
}
catch (Exception ex)
{
throw ex;
}
finally
{
conn.Close();
}
}
/// <summary>
/// 查询辅助类
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="reader"></param>
/// <returns></returns>
public List<T> GetListBySqlDataReader<T>(SqlDataReader reader)
{
Type type = typeof(T);
List<T> list = new List<T>();
while (reader.Read())
{
T t = (T)Activator.CreateInstance(type);
foreach (var prop in type.GetProperties())
{
prop.SetValue(t, reader[AttributeHelp.GetColNameByProp(prop)] is DBNull ? null : reader[AttributeHelp.GetColNameByProp(prop)]);
}
list.Add(t);
}
return list;
}
2.更新数据:
/// <summary>
/// 通过id更新单个对象
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="id"></param>
/// <returns></returns>
public bool Update<T>(T t) where T : BaseModel
{
try
{
Type type = typeof(T);
var propArr = type.GetProperties().Where(a => a.Name != "id");
string paramStr = string.Join(",", propArr.Select(a => string.Format(" [{0}]=@{1} ", AttributeHelp.GetColNameByProp(a), AttributeHelp.GetColNameByProp(a))));
StringBuilder sql = new StringBuilder();
sql.AppendFormat("update {0} set {1} where id={2} ", type.Name, paramStr, t.id);
using (conn = new SqlConnection(_connStr))
{
conn.Open();
SqlParameter[] paraArr = propArr.Select(a => new SqlParameter { ParameterName = AttributeHelp.GetColNameByProp(a), Value = (a.GetValue(t) ?? System.DBNull.Value) }).ToArray();
SqlCommand cmd = new SqlCommand(sql.ToString(), conn);
cmd.Parameters.AddRange(paraArr);
return cmd.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
conn.Close();
}
}
public class Company : BaseModel
{
public string cp_name { get; set; }
[AttributeByColName("desc")]
public string cp_desc { get; set; }
public string create_user { get; set; }
public string modify_user { get; set; }
public string delete_user { get; set; }
public DateTime? create_time { get; set; }
public DateTime? modify_time { get; set; }
public DateTime? delete_time { get; set; }
public bool is_deleted { get; set; }
}
二:关于?和 ?? 的区别
1. 可空类型修饰符(?): 引用类型可以使用空引用表示一个不存在的值,而值类型通常不能表示为空。 例如:string str=null; 是正确的,int i=null; 编译器就会报错。 为了使值类型也可为空,就可以使用可空类型,即用可空类型修饰符"?"来表示,表现形式为"T?" 例如:int? 表示可空的整形,DateTime? 表示可为空的时间。 T? 其实是System.Nullable(泛型结构)的缩写形式,也就意味着当你用到T?时编译器编译 时会把T?编译成System.Nullable的形式。 例如:int?,编译后便是System.Nullable的形式。 2. 三元(运算符)表达式(?:): 例如:x?y:z 表示如果表达式x为true,则返回y;如果x为false,则返回z,是省略if{}else{}的简单形式。 3. 空合并运算符(??): 用于定义可空类型和引用类型的默认值。如果此运算符的左操作数不为null,则此运算符将返回左操作数,否则返回右操作数。 例如:a??b 当a为null时则返回b,a不为null时则返回a本身。 空合并运算符为右结合运算符,即操作时从右向左进行组合的。如,“a??b??c”的形式按“a??(b??c)”计算。