/// <summary> /// 解析实体类型的元数据(允许不定义TableAttribute) /// </summary> public static TableMetaData ParseTableMetaData(Type entityType) { TableMetaData table = new TableMetaData(); table.EntityType = entityType; //表名 TableAttribute[] tableAttributes = (TableAttribute[])entityType.GetCustomAttributes(typeof(TableAttribute), false); if (tableAttributes.Length > 0) { table.TableName = string.IsNullOrEmpty(tableAttributes[0].TableName) ? entityType.Name : tableAttributes[0].TableName; } //列集合 table.NormalColumns = new List <ColumnMetaData>(); table.PropertiesDic = new Dictionary <string, PropertyMetaData>(); foreach (PropertyInfo pi in entityType.GetProperties()) { string piNameUpper = pi.Name.ToUpper(); if (table.PropertiesDic.ContainsKey(piNameUpper)) { throw new MappingException(string.Format("实体类型{0}中的属性名或列名{1}重复", entityType.Name, pi.Name)); } PropertyMetaData propertyData = new PropertyMetaData(); propertyData.PropertyType = pi.PropertyType; propertyData.PropertyAccessor = new DynamicPropertyAccessor(pi); table.PropertiesDic.Add(piNameUpper, propertyData); ColumnAttribute[] columnAttributes = (ColumnAttribute[])pi.GetCustomAttributes(typeof(ColumnAttribute), false); if (columnAttributes.Length > 0) { #region 解析Column ColumnMetaData column = new ColumnMetaData(); column.PropertyType = pi.PropertyType; column.PropertyAccessor = new DynamicPropertyAccessor(pi); column.ColumnName = string.IsNullOrEmpty(columnAttributes[0].ColumnName) ? pi.Name : columnAttributes[0].ColumnName; column.ColumnCategory = columnAttributes[0].ColumnCategory; switch (column.ColumnCategory) { case Category.Normal: case Category.ReadOnly: table.NormalColumns.Add(column); break; case Category.IdentityKey: case Category.Key: if (table.PKColumn != null) { throw new MappingException(string.Format("实体类型{0}中定义了超过一个主键列:{1}和{2}", entityType.Name, table.PKColumn.ColumnName, column.ColumnName)); } table.PKColumn = column; break; case Category.Version: if (column.PropertyType != typeof(DateTime) && column.PropertyType != typeof(Int32) && column.PropertyType != typeof(Int64)) { throw new MappingException(string.Format("实体类型{0}中的Version列{1}的数据类型无效", entityType.Name, column.ColumnName)); } if (table.VersionColumn != null) { throw new MappingException(string.Format("实体类型{0}中定义了超过一个Version列:{1}和{2}", entityType.Name, table.VersionColumn.ColumnName, column.ColumnName)); } table.VersionColumn = column; break; default: throw new NotSupportedException("无效的ColumnCategory:" + columnAttributes[0].ColumnCategory); } //如果列名与属性名不同,则添加两个属性到dic中 if (!string.IsNullOrEmpty(columnAttributes[0].ColumnName)) { string columnNameUpper = columnAttributes[0].ColumnName.ToUpper(); if (columnNameUpper != piNameUpper) { if (table.PropertiesDic.ContainsKey(columnNameUpper)) { throw new MappingException(string.Format("实体类型{0}中的属性名或列名{1}重复", entityType.Name, columnAttributes[0].ColumnName)); } table.PropertiesDic.Add(columnNameUpper, propertyData); } } #endregion } } if (!string.IsNullOrEmpty(table.TableName) && table.PKColumn == null && table.NormalColumns.Count == 0) { throw new MappingException(string.Format("实体类型:{0}中定义了TableAttribute,但未找到定义ColumnAttribute的列", entityType.Name)); } return(table); }
public void Update(object obj, bool ignoreVersionCheck, List <string> updateColumnList) { TableMetaData table = MetaDataCacheManager.GetTableMetaData(obj.GetType()); if (table.PKColumn == null) { throw new InvalidOperationException(string.Format("类型{0}未定义主键列,无法执行更新操作", obj.GetType().Name)); } List <string> columnNames = new List <string>(); List <object> columnValues = new List <object>(); List <DbType> columnDbTypes = new List <DbType>(); object newVersion = null; object oldVersion = null; if (table.VersionColumn != null) { #region 处理标识列 columnNames.Add(table.VersionColumn.ColumnName); if (table.VersionColumn.PropertyType == typeof(DateTime)) { DateTime oldDt = (DateTime)table.VersionColumn.PropertyAccessor.GetValue(obj); if (!ignoreVersionCheck && oldDt == DateTime.MinValue) { throw new SqlException("更新对象时版本列的值为空"); } oldVersion = oldDt; DateTime dt = DateTime.Now; newVersion = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second); } else if (table.VersionColumn.PropertyType == typeof(Int32)) { oldVersion = table.VersionColumn.PropertyAccessor.GetValue(obj); newVersion = (int)oldVersion + 1; } else if (table.VersionColumn.PropertyType == typeof(Int64)) { oldVersion = table.VersionColumn.PropertyAccessor.GetValue(obj); newVersion = (long)oldVersion + 1; } else { throw new MappingException(string.Format("实体类型{0}中的Version列{1}的数据类型无效", obj.GetType().Name, table.VersionColumn.ColumnName)); } columnValues.Add(newVersion); columnDbTypes.Add(GetDbType(table.VersionColumn.PropertyType)); #endregion } if (updateColumnList.Count == 0) { foreach (ColumnMetaData column in table.NormalColumns) { if (column.ColumnCategory != Category.ReadOnly) { columnNames.Add(column.ColumnName); columnValues.Add(column.PropertyAccessor.GetValue(obj)); columnDbTypes.Add(GetDbType(column.PropertyType)); } } } else { //更新指定的列 foreach (string columnName in updateColumnList) { ColumnMetaData column = FindColumn(columnName, table.NormalColumns); if (column == null) { throw new SqlException("列名未找到或无效:" + columnName); } if (column.ColumnCategory != Category.ReadOnly) { columnNames.Add(column.ColumnName); columnValues.Add(column.PropertyAccessor.GetValue(obj)); columnDbTypes.Add(GetDbType(column.PropertyType)); } } } string format = "Update {0} Set {1} Where {2};"; StringBuilder tempUpdateString = new StringBuilder(); StringBuilder tempConditions = new StringBuilder(); for (int i = 0; i < columnNames.Count; i++) { tempUpdateString.AppendFormat("{0}=@{0},", columnNames[i]); } tempUpdateString.Remove(tempUpdateString.Length - 1, 1); //根据主键及版本列生成条件 tempConditions.AppendFormat("{0}=@{0}", table.PKColumn.ColumnName); if (!ignoreVersionCheck && table.VersionColumn != null) { tempConditions.AppendFormat(" And {0}=@Old_{0}", table.VersionColumn.ColumnName); } DbCommand dbCommand = _DbInstance.GetSqlStringCommand(string.Format(format, table.TableName, tempUpdateString, tempConditions)); for (int i = 0; i < columnNames.Count; i++) { _DbInstance.AddInParameter(dbCommand, "@" + columnNames[i], columnDbTypes[i], TransformToSqlParamValue(columnValues[i])); } _DbInstance.AddInParameter(dbCommand, "@" + table.PKColumn.ColumnName, GetDbType(table.PKColumn.PropertyType), table.PKColumn.PropertyAccessor.GetValue(obj)); if (!ignoreVersionCheck && table.VersionColumn != null) { _DbInstance.AddInParameter(dbCommand, "@Old_" + table.VersionColumn.ColumnName, GetDbType(table.VersionColumn.PropertyType), oldVersion); } //执行sql命令 int count; try { count = _DbInstance.ExecuteNonQuery(dbCommand); } catch (Exception ex) { throw new SqlException(ex.Message, LogHelper.GetSqlString(dbCommand), ex); } if (count == 0) { throw new StaleObjectStateException("在更新到数据库时,受影响的记录数为0,请检查更新的条件是否正确,或者对象的状态已过期。"); } if (count > 1) { throw new SqlException("更新的记录超过一条"); } if (table.VersionColumn != null) { table.VersionColumn.PropertyAccessor.SetValue(obj, newVersion); } }