private static T BuildItem <T>(SqliteDataReader reader, FieldInfo[] fieldInfos, PropertyInfo[] propertyInfos) where T : class, new() { T item = new T(); foreach (FieldInfo field in fieldInfos) { DbFieldAttribute dbFieldAttr = GetDbFieldAttribute(field); if (dbFieldAttr == null) { continue; } object v = GetValue(reader, field.FieldType, dbFieldAttr); field.SetValue(item, v); } foreach (PropertyInfo property in propertyInfos) { DbFieldAttribute dbFieldAttr = GetDbFieldAttribute(property); if (dbFieldAttr == null) { continue; } object v = GetValue(reader, property.PropertyType, dbFieldAttr); property.SetValue(item, v, null); } return(item); }
/// <summary> /// 从数据库中删除一条记录 /// </summary> public static async Task DeleteEntity <T>(DbConnector connector, int id) where T : new() { Type entityType = typeof(T); if (!(DbTableAttribute.GetCustomAttribute(entityType, typeof(DbTableAttribute)) is DbTableAttribute tableAttr)) { throw new Exception("类型" + entityType.FullName + "没有标记DbTableAttribute特性"); } string tableName = tableAttr.TableName; string primaryKey = string.Empty; foreach (PropertyInfo property in entityType.GetProperties()) { if (!property.IsDefined(typeof(DbFieldAttribute), false)) { continue; } DbFieldAttribute fldAttr = (DbFieldAttribute)(Attribute.GetCustomAttribute(property, typeof(DbFieldAttribute))); if (fldAttr.IsPrimaryKey) { primaryKey = fldAttr.FieldName; } } if (string.IsNullOrEmpty(tableName) || string.IsNullOrEmpty(primaryKey)) { throw new Exception("类型" + entityType.FullName + "不支持数据库操纵"); } await DeleteEntity(connector, tableName, primaryKey, id); }
static SqlParameter GenerateSqlParameter(DbFieldAttribute fldAttr, Type memberType, object value) { string parameterName = "@" + fldAttr.FieldName; if (value != null) { if (fldAttr.FieldType == SqlDbType.BigInt || fldAttr.FieldType == SqlDbType.Int || fldAttr.FieldType == SqlDbType.SmallInt || fldAttr.FieldType == SqlDbType.TinyInt || fldAttr.FieldType == SqlDbType.UniqueIdentifier || fldAttr.FieldType == SqlDbType.Xml ) { SqlParameter p = new SqlParameter(parameterName, fldAttr.FieldType) { Value = value }; return(p); } else { return(new SqlParameter(parameterName, value)); } } else { SqlDbType dbType = (fldAttr.TypeDefined)? fldAttr.FieldType: ValueHelper.MapSystemTypeToSqlDbType(memberType); return(new SqlParameter(parameterName, dbType) { Value = DBNull.Value }); } }
internal DbColumnMapping(PropertyInfo property, DbFieldAttribute attr) { this.FieldAttribute = attr; this.Property = property; this.ColumnType = property.PropertyType; this.ColumnName = attr.FieldName ?? property.Name; this.PrimaryKeyAttribute = property.GetCustomAttribute <DbFieldPrimaryKeyAttribute>(); }
internal DbColumnMapping(FieldInfo field, DbFieldAttribute attr) { this.FieldAttribute = attr; this.Field = field; this.ColumnType = field.FieldType; this.ColumnName = attr.FieldName ?? field.Name; this.PrimaryKeyAttribute = field.GetCustomAttribute <DbFieldPrimaryKeyAttribute>(); }
/// <summary> /// 从一个对象实例中通过检查DbTable和DbField特性来构建一个用于插入数据行的T-SQL语句。 /// 为了防止SQL注入,该SQL语句是参数化的,并且通过out参数返回由entity对象实例中包括的值构建出来的SqlParameter集 /// </summary> /// <param name="entity">准备用作插入新行的对象实例</param> /// <param name="parameters">参数化的每一列输入参数,包含了值</param> /// <param name="primaryKey">主键输出参数,用来返回新行的主键</param> /// <returns></returns> static string BuildInsertSql(object entity, out SqlParameter[] parameters, out SqlParameter primaryKey) { Type type = entity.GetType(); object[] tableAttributes = type.GetCustomAttributes(typeof(DbTableAttribute), false); if (tableAttributes == null || tableAttributes.Length != 1) { throw new Exception("使用BuildInsertSql()方法,类" + type.FullName + "必须标记唯一的DbTable特性。"); } DbTableAttribute tableAttr = (DbTableAttribute)tableAttributes[0]; StringBuilder fieldBuilder = new StringBuilder(), valueBuilder = new StringBuilder(); List <SqlParameter> parametersList = new List <SqlParameter>(); primaryKey = null; foreach (MemberInfo m in type.GetMembers(BindingFlags.Instance | BindingFlags.Public)) { #region loop values bool isDefine = m.IsDefined(typeof(DbFieldAttribute), false); if (!isDefine) { continue; } DbFieldAttribute fldAttr = (DbFieldAttribute)(DbFieldAttribute.GetCustomAttribute(m, typeof(DbFieldAttribute))); if (fldAttr.IsPrimaryKey) { primaryKey = new SqlParameter("@" + fldAttr.FieldName, SqlDbType.Int) { Direction = ParameterDirection.Output }; parametersList.Add(primaryKey); continue; } if ((fldAttr.Usage & DbFieldUsage.InsertParameter) != DbFieldUsage.InsertParameter) { continue; } fieldBuilder.Append(",[" + fldAttr.FieldName + "]"); valueBuilder.Append(",@" + fldAttr.FieldName); Type memberType; object memberValue = ValueHelper.GetMemberValue(m, fldAttr, entity, out memberType); SqlParameter parameter = GenerateSqlParameter(fldAttr, memberType, memberValue); parametersList.Add(parameter); #endregion } fieldBuilder.Remove(0, 1); valueBuilder.Remove(0, 1); string sql = @$ " INSERT INTO {tableAttr.TableName}({fieldBuilder.ToString()}) VALUES({valueBuilder.ToString()});
/// <summary> /// 从实体对象中读取属性或字段值,用于给SqlParameter参数设置正确的值。 /// 尤其是对IsForeignKey(负数或0)和DateTime类型的值(早于1900-01-01),设置DbNull.Value给参数 /// </summary> /// <param name="member"></param> /// <param name="attr"></param> /// <param name="entity"></param> /// <param name="dataType"></param> /// <returns></returns> public static object GetMemberValue(MemberInfo member, DbFieldAttribute attr, object entity, out Type dataType) { object obj; if (member.MemberType == MemberTypes.Field) { FieldInfo field = (FieldInfo)member; dataType = field.FieldType; obj = field.GetValue(entity); } else if (member.MemberType == MemberTypes.Property) { PropertyInfo property = (PropertyInfo)member; dataType = property.PropertyType; obj = property.GetValue(entity, null); } else { throw new Exception("必须是字段或者属性。"); } if (attr.IsForeignKey) { if (attr.FieldType == SqlDbType.BigInt || attr.FieldType == SqlDbType.Int || attr.FieldType == SqlDbType.SmallInt || attr.FieldType == SqlDbType.TinyInt ) { if (Convert.ToInt32(obj) <= 0) { return(null); } } } if (dataType.ToString() == "System.DateTime") { if ((DateTime)obj <= new DateTime(1900, 1, 1)) { return(null); } } return(obj); }
private static List <Tuple <PropertyInfo, DbFieldAttribute> > GetPropertyCache(Type t) { if (propertyCache.ContainsKey(t)) { return(propertyCache[t].ToList()); // always return a copy } List <Tuple <PropertyInfo, DbFieldAttribute> > newValue = new List <Tuple <PropertyInfo, DbFieldAttribute> >(); var properties = t.GetProperties().Where(prop => prop.IsDefined(typeof(DbFieldAttribute), false)); foreach (var p in properties) { DbFieldAttribute f = p.GetAttributeOfType <DbFieldAttribute>(); newValue.Add(new Tuple <PropertyInfo, DbFieldAttribute>(p, f)); } propertyCache.Add(t, newValue); return(newValue); }
/// <summary> /// 使用关键字id从数据库中查找,返回entityType类的实例 /// </summary> /// <param name="connector"></param> /// <param name="entityType"></param> /// <param name="id"></param> /// <returns></returns> public static async Task <T> FindEntity <T>(DbConnector connector, int id) where T : new() { Type entityType = typeof(T); object[] tableAttributes = entityType.GetCustomAttributes(typeof(DbTableAttribute), false); if (tableAttributes == null || tableAttributes.Length != 1) { throw new Exception("使用FindEntity()方法,类" + entityType.FullName + "必须标记唯一的DbTable特性。"); } DbTableAttribute tableAttr = (DbTableAttribute)tableAttributes[0]; string tableName = tableAttr.TableName; string keyName = string.Empty; foreach (PropertyInfo propertyInfo in entityType.GetProperties()) { if (!propertyInfo.IsDefined(typeof(DbFieldAttribute), false)) { continue; } DbFieldAttribute fldAttr = (DbFieldAttribute)(DbFieldAttribute.GetCustomAttribute(propertyInfo, typeof(DbFieldAttribute))); if (fldAttr.IsPrimaryKey) { keyName = fldAttr.FieldName; break; } } string sql = string.Format(@"SELECT * FROM {0} WHERE {1}={2};", tableName, keyName, id); DataTable table = await connector.ExecuteSqlQueryTable(sql); if (table == null || table.Rows.Count == 0) { return(default(T)); } else { object obj = Activator.CreateInstance(entityType); ValueHelper.FulfillEntity(entityType, table.Rows[0], ref obj); return((T)obj); } }
/// <summary> /// 使用row中的值填充对象entity /// </summary> /// <param name="type"></param> /// <param name="row"></param> /// <param name="entity"></param> public static void FulfillEntity(Type type, DataRow row, ref object entity) { foreach (MemberInfo m in type.GetMembers(BindingFlags.Instance | BindingFlags.Public)) { Attribute attr = DbFieldAttribute.GetCustomAttribute(m, typeof(DbFieldAttribute)); if (attr == null) { continue; } DbFieldAttribute dAttr = (DbFieldAttribute)attr; if ((dAttr.Usage & DbFieldUsage.MapResultTable) != DbFieldUsage.MapResultTable) { continue; } try { if (m.MemberType == MemberTypes.Field) { //the member is a DbField; object value = ValueHelper.GetTableRowValue(row, dAttr.FieldName, ((FieldInfo)m).FieldType); ((FieldInfo)m).SetValue(entity, value); } else if (m.MemberType == MemberTypes.Property) { //the member is a DbField; object value = GetTableRowValue(row, dAttr.FieldName, ((PropertyInfo)m).PropertyType); ((PropertyInfo)m).SetValue(entity, value, null); } } catch (Exception ex) { throw new Exception("成员[" + m.Name + "]出错" + ex.ToString()); } } }
protected void _AnalyseDbClz(int rowCount, Func <Type, int, object> getNextElement) { FieldInfo[] fieldInfos = GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo info = null; DbFieldAttribute attr = null; for (int i = 0; i < fieldInfos.Length; ++i) { info = fieldInfos[i]; attr = Attribute.GetCustomAttribute(info, typeof(DbFieldAttribute), true) as DbFieldAttribute; if (attr == null || attr.FieldType == DbFieldType.None) { continue; } object sequenceData = null; switch (attr.FieldType) { case DbFieldType.Array: sequenceData = DataImporter.GenArray(info.FieldType, rowCount, idx => getNextElement(DataImporter.GetArrayElementType(info.FieldType), idx)); break; case DbFieldType.List: sequenceData = DataImporter.GenList(info.FieldType, rowCount, idx => getNextElement(DataImporter.GetGenericListElementType(info.FieldType), idx)); break; default: continue; } info.SetValue(this, sequenceData); } }
public sys_log EntityFields <T>(T entity) { sys_log slog = new sys_log(); Dictionary <string, object> fields = new Dictionary <string, object>(); Type type = entity.GetType(); slog.tablename = type.Name; PropertyInfo[] proinfos = type.GetProperties(); foreach (var item in proinfos) { string colname = string.Empty; object colval = null; var attrs = item.GetCustomAttributes(typeof(DbFieldAttribute)); if (attrs.Count() > 0) { DbFieldAttribute attr = attrs.First() as DbFieldAttribute; colname = attr.FieldName; colval = item.GetValue(entity); fields.Add(colname, colval); } } slog.fields = fields.Where(t => t.Value != null).ToDictionary(t => t.Key, t => t.Value); StringBuilder cols = new StringBuilder(); StringBuilder vals = new StringBuilder(); slog.fields.ToList().ForEach(t => cols.Append(t.Key + ",")); slog.fields.ToList().ForEach(t => vals.Append($"'{t.Value}',")); StringBuilder sql = new StringBuilder(); sql.Append("select "); sql.Append(cols.ToString().Substring(0, cols.Length - 1)); sql.Append($" from {slog.tablename} where id = :id "); slog.querysql = sql.ToString(); slog.insertsql = $"insert into {slog.tablename} ({cols.ToString().Substring(0, cols.Length - 1)}) values ({vals.ToString().Substring(0, vals.Length - 1)})"; return(slog); }
static object GetValue(SqliteDataReader reader, System.Type fieldType, DbFieldAttribute attr) { object v = null; if (fieldType == typeof(int)) { v = Db.GetInt(reader, attr.FieldName); } else if (fieldType == typeof(int[])) { v = PETools.Db.GetIntArray(reader, attr.FieldName); } else if (fieldType == typeof(float)) { v = Db.GetFloat(reader, attr.FieldName); } else if (fieldType == typeof(float[])) { v = PETools.Db.GetFloatArray(reader, attr.FieldName); } else if (fieldType == typeof(string)) { v = Db.GetString(reader, attr.FieldName); } else if (fieldType == typeof(bool)) { v = Db.GetBool(reader, attr.FieldName); } else if (fieldType == typeof(Color)) { v = Db.GetColor(reader, attr.FieldName); } else if (fieldType.IsEnum) { if (attr.EnumValue) { v = Db.GetInt(reader, attr.FieldName); } else { v = System.Enum.Parse(fieldType, Db.GetString(reader, attr.FieldName)); } } else if (fieldType == typeof(Vector3)) { v = PETools.Db.GetVector3(reader, attr.FieldName); } else if (fieldType == typeof(Vector3[])) { v = PETools.Db.GetVector3Array(reader, attr.FieldName); } else if (fieldType == typeof(Quaternion)) { v = PETools.Db.GetQuaternion(reader, attr.FieldName); } else if (fieldType == typeof(Quaternion[])) { v = PETools.Db.GetQuaternionArray(reader, attr.FieldName); } else { Debug.LogError("not supported value type:" + fieldType); } return(v); }
private static T BuildListItem <T>(SQLiteDataReader reader, FieldInfo[] fieldInfos, PropertyInfo[] propertyInfos, int cacheId = 0) where T : class, new() { if (cacheId == 0 || cacheId != attrTEMP) { dbFieldAttrTEMP = null; dbPropertyAttrTEMP = null; } attrTEMP = cacheId; T item = new T(); for (int i = 0; i < fieldInfos.Length; i++) { var field = fieldInfos[i]; if (dbFieldAttrTEMP == null) { dbFieldAttrTEMP = new List <DbFieldAttribute>(8); } if (dbFieldAttrTEMP.Count < fieldInfos.Length) { DbFieldAttribute dbFieldAttr = GetDbFieldAttribute(field); dbFieldAttrTEMP.Add(dbFieldAttr); } var atrr = dbFieldAttrTEMP[i]; if (atrr == null) { continue; } object v = GetValue(reader, field.FieldType, atrr); field.SetValue(item, v); } for (int i = 0; i < propertyInfos.Length; i++) { var property = propertyInfos[i]; if (dbPropertyAttrTEMP == null) { dbPropertyAttrTEMP = new List <DbFieldAttribute>(8); } if (dbPropertyAttrTEMP.Count < fieldInfos.Length) { DbFieldAttribute dbPropertyttr = GetDbFieldAttribute(property); dbPropertyAttrTEMP.Add(dbPropertyttr); } var atrr = dbPropertyAttrTEMP[i]; if (atrr == null) { continue; } object v = GetValue(reader, property.PropertyType, atrr); property.SetValue(item, v, null); } return(item); }
private static object GetValue(SQLiteDataReader reader, System.Type fieldType, DbFieldAttribute attr) { object v = null; if (fieldType == typeof(int)) { v = Converter.ToInt(reader, attr.FieldName); } else if (fieldType == typeof(byte)) { v = (byte)Converter.ToInt(reader, attr.FieldName); } else if (fieldType == typeof(float)) { v = Converter.ToFloat(reader, attr.FieldName); } else if (fieldType == typeof(string)) { v = Converter.ToString(reader, attr.FieldName); } else if (fieldType == typeof(bool)) { v = Converter.ToBool(reader, attr.FieldName); } else if (fieldType == typeof(Vector3)) { v = Converter.ToVector3(reader, attr.FieldName, attr.Separator); } else if (fieldType == typeof(Vector2)) { v = Converter.ToVector2(reader, attr.FieldName, attr.Separator); } else if (fieldType.IsEnum) { v = System.Enum.Parse(fieldType, Converter.ToString(reader, attr.FieldName)); } else if (fieldType == typeof(int[])) { v = Converter.GetIntArray(reader, attr.FieldName, attr.Separator); } else if (fieldType == typeof(float[])) { v = Converter.ToFloatArray(reader, attr.FieldName, attr.Separator); } else if (fieldType == typeof(string[])) { v = Converter.ToStringArray(reader, attr.FieldName, attr.Separator); } else { Debug.LogError("not supported value type:" + fieldType); } return(v); }
public void UpdateLog <T>(T entity, T orginalobj) { if (!islog) { return; } object id = 0; StringBuilder txt = new StringBuilder(); sys_log slog = EntityFields <T>(entity); slog.fields.TryGetValue("id", out id); sys_user user = CacheManager.Instance().Current_User; txt.Append($"[{user.name}]更新{slog.tablename},"); var cnames = slog.fields.Select(t => t.Key); Type orgtype = orginalobj.GetType(); PropertyInfo[] orgproinfos = orgtype.GetProperties().Where(t => cnames.Contains(t.Name)).ToArray(); foreach (var item in orgproinfos) { string fn = string.Empty; object fv = null; object fvnew = null; var orgattrs = item.GetCustomAttributes(typeof(DbFieldAttribute)); if (orgattrs.Count() > 0) { DbFieldAttribute attr = orgattrs.First() as DbFieldAttribute; fn = attr.FieldName; fv = item.GetValue(orginalobj); string coltype = item.PropertyType.Name; slog.fields.TryGetValue(fn, out fvnew); switch (coltype) { case "Int32": if (Convert.ToInt32(fv) != Convert.ToInt32(fvnew ?? 0)) { txt.Append($"[{attr.Label}]:{fv}->{fvnew},"); } break; case "String": if (fv.ToString() != (fvnew ?? "").ToString()) { txt.Append($"[{attr.Label}]:{fv}->{fvnew},"); } break; case "DateTime": if (Convert.ToDateTime(fv) != Convert.ToDateTime(fvnew)) { txt.Append($"[{attr.Label}]:{fv}->{fvnew},"); } break; case "Double": if (Convert.ToDouble(fv) != Convert.ToDouble(fvnew ?? 0)) { txt.Append($"[{attr.Label}]:{fv}->{fvnew},"); } break; case "Float": if (Convert.ToSingle(fv) != Convert.ToSingle(fvnew ?? 0)) { txt.Append($"[{attr.Label}]:{fv}->{fvnew},"); } break; case "Decimal": if (Convert.ToDecimal(fv) != Convert.ToDecimal(fvnew ?? 0)) { txt.Append($"[{attr.Label}]:{fv}->{fvnew},"); } break; default: break; } } } log.Info(txt.ToString()); }
/// <summary> /// 使用提供的条件查询数据库(表由entityType指定),返回满足条件的记录(分页) /// </summary> /// <typeparam name="T">要查询的实体类型,标记了DbTable和DbField特性的类,并且具有空白构造函数</typeparam> /// <param name="connector"></param> /// <param name="criteria">查询条件字典,键是PropertyName,条件仅支持=比较,条件间仅支持AND运算</param> /// <param name="pageIndex">从0开始的返回页索引</param> /// <param name="pageSize">每页几行记录</param> /// <param name="sortProperty">用于排序的PropertyName(如为空则使用关键字)</param> /// <param name="descending">是否倒序排列</param> /// <param name="total">符合条件的记录总数</param> /// <returns></returns> public static async Task <PagedQuery <T> > SearchEntities <T>(DbConnector connector, Dictionary <string, object> criteria, int pageIndex, int pageSize, string sortProperty, bool descending) where T : new() { Type entityType = typeof(T); if (!(DbTableAttribute.GetCustomAttribute(entityType, typeof(DbTableAttribute)) is DbTableAttribute tableAttr)) { throw new Exception("类型" + entityType.FullName + "没有标记DbTableAttribute特性"); } string selectClause = "SELECT * "; string fromClause = "FROM " + tableAttr.TableName; string orderBy; #region 正确处理orderBy DbFieldAttribute sortFieldAttr = null; if (string.IsNullOrWhiteSpace(sortProperty)) { //如果没有传递sortProperty参数, 则使用PrimaryKey foreach (PropertyInfo property in entityType.GetProperties()) { DbFieldAttribute fldAttr = DbFieldAttribute.GetCustomAttribute(property, typeof(DbFieldAttribute)) as DbFieldAttribute; if (fldAttr != null && fldAttr.IsPrimaryKey) { sortFieldAttr = fldAttr; break; } } } else { PropertyInfo property = entityType.GetProperty(sortProperty); if (property == null) { throw new Exception(string.Format("类型{0}中没有找到{1}属性用于排序", entityType.FullName, sortProperty)); } sortFieldAttr = DbFieldAttribute.GetCustomAttribute(property, typeof(DbFieldAttribute)) as DbFieldAttribute; } if (sortFieldAttr == null) { throw new Exception("类型" + entityType.FullName + "没有标记IsPrimaryKey=true的DbField特性"); } if (descending) { orderBy = sortFieldAttr.FieldName + " DESC"; } else { orderBy = sortFieldAttr.FieldName; } #endregion StringBuilder whereBuilder = new StringBuilder(); List <SqlParameter> sqlParameters = new List <SqlParameter>(); if (criteria != null) { foreach (string conditionName in criteria.Keys) { if (criteria[conditionName] == null || criteria[conditionName].ToString().Length == 0) { continue; } PropertyInfo conditionProperty = entityType.GetProperty(conditionName); if (conditionProperty == null) { throw new Exception(string.Format("类型{0}中没有找到{1}属性用于查询条件", entityType.FullName, conditionName)); } DbFieldAttribute conditionAttr = DbFieldAttribute.GetCustomAttribute(conditionProperty, typeof(DbFieldAttribute)) as DbFieldAttribute; if (conditionAttr == null) { throw new Exception(string.Format("类型{0}的{1}属性没有标记DbFieldAttribute特性, 无法用于数据库查询", entityType.FullName, conditionName)); } SqlParameter parameter = GenerateSqlParameter(conditionAttr, conditionProperty.PropertyType, criteria[conditionName]); sqlParameters.Add(parameter); whereBuilder.AppendFormat("[{0}]=@{0} ", conditionAttr.FieldName); whereBuilder.Append("AND "); } } if (whereBuilder.Length > 0) { whereBuilder.Remove(whereBuilder.Length - 4, 4); } string sql = BuildPagedSelectSql(selectClause, fromClause, whereBuilder.ToString(), orderBy, pageIndex, pageSize); DataSet ds = await connector.ExecuteSqlQuerySet(sql, sqlParameters.ToArray()); PagedQuery <T> result = new PagedQuery <T>(); if (ds != null && ds.Tables.Count == 2) { result.Total = (int)ds.Tables[0].Rows[0][0]; ds.Tables[1].TableName = "result"; result.Records = await Task.Run(() => ValueHelper.WrapEntities <T>(ds.Tables[1])); } else { result.Total = 0; result.Records = new T[0]; } ds.Dispose(); return(result); }