/// <summary> /// 设置字符串类型的属性字段在数据库读写的时候使用的字段长度。 /// 注意这这个设置将一直有效且只对字符串类型的字段有效,除非再次重新设置。 /// </summary> /// <param name="fieldName">字段名称</param> /// <param name="length">字段长度</param> /// <param name="dbType">字符串字段的字段类型</param> protected internal void SetStringFieldSize(string fieldName, int length, System.Data.DbType dbType) { if (length > 0) { string key = string.Format("{0}_{1}", GetGolbalEntityID(), fieldName); StringFieldSize[key] = new SimplyField(length, dbType); } }
/// <summary> /// 将字典形式的参数数据,转换成数据库格式的参数素组 /// </summary> /// <param name="dictPara">表字段名字典</param> /// <param name="db">数据访问对象</param> /// <returns></returns> protected internal static IDataParameter[] GetParameters(Dictionary <string, TableNameField> dictPara, AdoHelper db) { if (dictPara == null) { return(null); } IDataParameter[] paras = new IDataParameter[dictPara.Count]; int index = 0; foreach (string key in dictPara.Keys) { object Value = dictPara[key]; if (Value is IDataParameter) { paras[index] = (IDataParameter)Value; } else { string paraName = key.StartsWith("@")?key.Substring(1):key; //参数名无需加上 ParameterChar //if (!key.StartsWith(db.GetParameterChar)) // paraName = db.GetParameterChar + key.Substring(1); var tnf = dictPara[key]; paras[index] = db.GetParameter(paraName, tnf.FieldValue); //为字符串类型的参数指定长度 edit at 2012.4.23 //增加判断tnf.Name!=null,这可能是因为使用了自定义查询的SqlMap的OQL,感谢网友 吉林-stdbool 发现此问题 if (tnf.Name != null && paras[index].Value != null && paras[index].Value.GetType() == typeof(string)) { //增加字符串长度的检查,如果值得长度大于定义的长度,抛出异常提示 2014.10.21 //int size = tnf.Entity.GetStringFieldSize(tnf.Field); //采用下面的方法,避免没有实体类元数据缓存 edit at 2015-12-5 SimplyField sf = EntityFieldsCache.Item(tnf.Entity.GetType()).GetPropertyFieldSize(tnf.Field, tnf.Entity); int size = sf.FieldLength; if (size != 0) //如果字段不是text等类型 { int length = paras[index].Value.ToString().Length; //if (length > size+2) //处理 like查询可能增加 %% 匹配的情况 //特别注意: //如果size==Int.Max,那么 size+2 会得到负数,从而导致 length > size+2 表达式为false //所以,修改成下面的样子,理论上不会再出错了。 //感谢网友 广州-银古 朋友发现此 bug ,2017.2.16 if (length - 2 > size && size > 0) { throw new NotSupportedException("当前实体类映射的字段" + paraName + " 长度没有定义或者长度小于了当前实际值的长度:" + length + ",请在实体类定义里面使用 setProperty 的重载方法指定合适的字段长度。"); } if (size > 0) { ((IDbDataParameter)paras[index]).Size = size; ((IDbDataParameter)paras[index]).DbType = sf.FieldDbType; //由实体类指定字段类型 } else { ((IDbDataParameter)paras[index]).Size = Math.Abs(size); ((IDbDataParameter)paras[index]).DbType = DbType.AnsiString; } } } } index++; } return(paras); }
/// <summary> /// 为实体类的一个属性创建对应的数据库表的列的脚本 /// </summary> /// <param name="db"></param> /// <param name="entity"></param> /// <param name="field"></param> /// <returns></returns> public string CreateTableColumnScript(AdoHelper db, EntityBase entity, string field) { Type t = this.GetPropertyType(field); object defaultValue = null; if (t == typeof(string)) { defaultValue = ""; } else if (t == typeof(byte[])) { defaultValue = new byte[1];//这里只是构造默认值,不需要实际的长度 } else { defaultValue = Activator.CreateInstance(t); } IDataParameter para = db.GetParameter(field, defaultValue); //需要再获取参数长度 string temp = ""; if (t == typeof(string)) { SimplyField sf = entity.GetStringFieldSize(field); int length = sf.FieldLength; if (length == 0) //实体类未定义属性字段的长度 { string fieldType = "text"; if (db is SqlServer) //此处要求SqlServer 2005以上,SqlServer2000 不支持 { fieldType = "varchar(max)"; } if (db.CurrentDBMSType == DBMSType.SqlServerCe) { fieldType = "ntext"; } temp = temp + "[" + field + "] " + fieldType; } else if (length > 0) { //并不是所有数据库都支持nvarchar,有关数据库字符串类型的详细支持,请看 http://www.cnblogs.com/hantianwei/p/3152517.html string fieldType = string.Empty; if (sf.FieldDbType == DbType.String) { fieldType = "nvarchar"; } else if (sf.FieldDbType == DbType.AnsiString) { fieldType = "varchar"; } else if (sf.FieldDbType == DbType.AnsiStringFixedLength) { fieldType = "char"; } else if (sf.FieldDbType == DbType.StringFixedLength) { fieldType = "nchar"; } else if (db.CurrentDBMSType == DBMSType.SqlServer || db.CurrentDBMSType == DBMSType.Oracle || db.CurrentDBMSType == DBMSType.SqlServerCe) { fieldType = "nvarchar"; } else { fieldType = "varchar"; } temp = temp + "[" + field + "] " + fieldType + "(" + length + ")"; } else if (length < 0) { temp = temp + "[" + field + "] varchar" + "(" + length + ")"; } } else if (t == typeof(byte[])) //感谢CSDN网友 ccliushou 发现此问题,原贴:http://bbs.csdn.net/topics/391967495 { int length = entity.GetStringFieldSize(field).FieldLength; temp = temp + "[" + field + "] " + db.GetNativeDbTypeName(para); if (length == 0) { temp = temp + "(max)"; } else { temp = temp + "(" + length + ")"; } } else { temp = temp + "[" + field + "] " + db.GetNativeDbTypeName(para); } if (field == entity.IdentityName) { if (db.CurrentDBMSType == PWMIS.Common.DBMSType.SqlServer || db.CurrentDBMSType == PWMIS.Common.DBMSType.SqlServerCe) { temp = temp + " IDENTITY(1,1)"; } else if (db.CurrentDBMSType == PWMIS.Common.DBMSType.Access) { temp = temp.Replace("Integer", " autoincrement"); } else if (db.CurrentDBMSType == PWMIS.Common.DBMSType.SQLite) { temp = temp + " autoincrement"; } else if (db.CurrentDBMSType == PWMIS.Common.DBMSType.MySql) { temp = temp + " AUTO_INCREMENT"; } else if (db.CurrentDBMSType == PWMIS.Common.DBMSType.PostgreSQL) { temp = temp + " DEFAULT nextval('" + entity.TableName + "_" + entity.IdentityName + "_" + "seq'::regclass) NOT NULL"; } else { //Oracle 采用序列和触发器,这里不处理 } } //identity(1,1) primary key //Access 要求主键申明必须在自增之后,否则语法错误 if (entity.PrimaryKeys.Contains(field)) { temp = temp + " PRIMARY KEY"; } return(db.GetPreparedSQL(temp)); }
/// <summary> /// 将字典形式的参数数据,转换成数据库格式的参数素组 /// </summary> /// <param name="dictPara">表字段名字典</param> /// <param name="db">数据访问对象</param> /// <returns></returns> protected internal static IDataParameter[] GetParameters(Dictionary <string, TableNameField> dictPara, AdoHelper db) { if (dictPara == null) { return(null); } if (db == null) { throw new ArgumentNullException("参数 db 不能为空!"); } IDataParameter[] paras = new IDataParameter[dictPara.Count]; int index = 0; foreach (string key in dictPara.Keys) { string paraName = key.StartsWith("@") ? key.Substring(1) : key; //参数名无需加上 ParameterChar //if (!paraName.StartsWith(db.GetParameterChar)) // paraName = db.GetParameterChar + paraName; var tnf = dictPara[key]; if (tnf == null) { continue; } paras[index] = db.GetParameter(paraName, tnf.FieldValue); //为字符串类型的参数指定长度 edit at 2012.4.23 //增加判断tnf.Name!=null,这可能是因为使用了自定义查询的SqlMap的OQL,感谢网友 吉林-stdbool 发现此问题 if (tnf.Name != null && paras[index].Value != null && paras[index].Value.GetType() == typeof(string)) { //增加字符串长度的检查,如果值得长度大于定义的长度,抛出异常提示 2014.10.21 //int size = tnf.Entity.GetStringFieldSize(tnf.Field); //采用下面的方法,避免没有实体类元数据缓存 edit at 2015-12-5 SimplyField sf = EntityFieldsCache.Item(tnf.Entity.GetType()).GetPropertyFieldSize(tnf.Field, tnf.Entity); int size = sf.FieldLength; if (size != 0) //如果字段不是text等类型 { int length = paras[index].Value.ToString().Length; //if (length > size+2) //处理 like查询可能增加 %% 匹配的情况 //特别注意: //如果size==Int.Max,那么 size+2 会得到负数,从而导致 length > size+2 表达式为false //所以,修改成下面的样子,理论上不会再出错了。 //感谢网友【广州-银古】朋友发现此 bug ,2017.2.16 //感谢网友【郑州-何】朋友发现在“OR”条件比较的查询下,查询的值应该可以超过字段长度的问题。 //为了确保安全,不被恶意攻击,这里限制为不得超过字段设定长度的40 倍。2018.5.30 if (length > size * 40 && size > 0) { throw new NotSupportedException("当前实体类映射的字段" + paraName + " 长度没有定义或者与该字段进行条件比较的值超过了字段设定长度的40倍,有被恶意攻击的风险!预定义的字段长度:" + length); } if (size > 0) { ((IDbDataParameter)paras[index]).Size = size; ((IDbDataParameter)paras[index]).DbType = sf.FieldDbType; //由实体类指定字段类型 } else { ((IDbDataParameter)paras[index]).Size = Math.Abs(size); ((IDbDataParameter)paras[index]).DbType = DbType.AnsiString; } } } index++; } return(paras); }