/// <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);
        }
Esempio n. 2
0
        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);
            }
        }