using System; using System.Collections; using System.Collections.Generic; using System.Text; using System.Data; using System.Data.SqlClient; using System.Reflection; using System.Xml; using System.IO; using System.Data.Common; using System.ComponentModel; using CYQ.Data.UI; using CYQ.Data.Cache; using CYQ.Data.SQL; using CYQ.Data.Tool; using System.Collections.Specialized; using System.Web; namespace CYQ.Data.Table { /// /// 表格 /// public partial class MDataTable { #region 隐式转换 /// /// 从DataReader隐式转换成MDataTable /// public static implicit operator MDataTable(DbDataReader sdr) { MDataTable dt = CreateFrom(sdr); if (sdr != null) { sdr.Close(); sdr.Dispose(); sdr = null; } return dt; } /// /// 从DataTable隐式转换成MDataTable /// public static implicit operator MDataTable(DataTable dt) { if (dt == null) { return null; } MDataTable mdt = new MDataTable(dt.TableName); if (dt.Columns != null && dt.Columns.Count > 0) { foreach (DataColumn item in dt.Columns) { mdt.Columns.Add(new MCellStruct(item.ColumnName, DataType.GetSqlType(item.DataType), item.ReadOnly, item.AllowDBNull, item.MaxLength)); } foreach (DataRow row in dt.Rows) { MDataRow mdr = mdt.NewRow(); for (int i = 0; i < dt.Columns.Count; i++) { mdr[i].Value = row[i]; } mdt.Rows.Add(mdr, row.RowState != DataRowState.Modified); } } return mdt; } /// /// 从行集合隐式转换成MDataTable /// /// /// public static implicit operator MDataTable(List rows) { return (MDataRowCollection)rows; } /// /// 将一行数据装载成一个表。 /// /// public static implicit operator MDataTable(MDataRow row) { MDataTable mTable = new MDataTable(row.TableName); mTable.Conn = row.Conn; mTable.LoadRow(row); return mTable; } /// /// 将一行数据装载成一个表。 /// /// public static implicit operator MDataTable(MDataRowCollection rows) { if (rows == null || rows.Count == 0) { return null; } MDataTable mdt = new MDataTable(rows[0].TableName); mdt.Conn = rows[0].Conn; mdt.Columns = rows[0].Columns; mdt.Rows.AddRange(rows); return mdt; } #endregion #region 属性 private MDataRowCollection _Rows; /// /// 表格行 /// public MDataRowCollection Rows { get { return _Rows; } } [NonSerialized] private object _DynamicData; /// /// 动态存储数据 /// public object DynamicData { get { return _DynamicData; } set { _DynamicData = value; } } public MDataTable() { Init("default", null); } public MDataTable(string tableName) { Init(tableName, null); } public MDataTable(string tableName, MDataColumn mdc) { Init(tableName, mdc); } private void Init(string tableName, MDataColumn mdc) { _Rows = new MDataRowCollection(this); _TableName = tableName; if (_Columns == null) { _Columns = new MDataColumn(this); if (mdc != null) { _Columns.AddRange(mdc); } } } private string _TableName = string.Empty; /// /// 表名 /// public string TableName { get { return _TableName; } set { _TableName = value; } } private string _Description = string.Empty; /// /// 表名描述 /// public string Description { get { if (string.IsNullOrEmpty(_Description)) { _Description = TableSchema.GetTableDescription(Conn, _TableName); if (string.IsNullOrEmpty(_Description)) { _Description = _TableName; } } return _Description; } set { _Description = value; } } private MDataColumn _Columns; /// /// 表格的架构列 /// public MDataColumn Columns { get { return _Columns; } set { _Columns = value; _Columns._Table = this; } } private string _Conn; /// /// 该表归属的数据库链接。 /// public string Conn { get { if (string.IsNullOrEmpty(_Conn)) { return AppConfig.DB.DefaultConn; } return _Conn; } set { _Conn = value; } } #endregion #region 方法 /// /// 新建一行 /// /// public MDataRow NewRow() { return NewRow(false); } /// /// 新建一行 /// /// 是否顺带添加到表中 /// public MDataRow NewRow(bool isAddToTable) { MDataRow mdr = new MDataRow(this); if (isAddToTable) { Rows.Add(mdr, false); } return mdr; } #region 准备新开始的方法 /// /// 使用本查询,得到克隆后的数据 /// public MDataTable Select(object where) { return Select(0, 0, where); } /// /// 使用本查询,得到克隆后的数据 /// public MDataTable Select(int topN, object where) { return Select(1, topN, where); } /// /// 使用本查询,得到克隆后的数据 /// public MDataTable Select(int pageIndex, int pageSize, object where, params object[] selectColumns) { return MDataTableFilter.Select(this, pageIndex, pageSize, where, selectColumns); } /// /// 使用本查询,得到原数据的引用。 /// public MDataRow FindRow(object where) { return MDataTableFilter.FindRow(this, where); } /// /// 使用本查询,得到原数据的引用。 /// public MDataRowCollection FindAll(object where) { return MDataTableFilter.FindAll(this, where); } /// /// 统计满足条件的行所在的索引 /// public int GetIndex(object where) { return MDataTableFilter.GetIndex(this, where); } /// /// 统计满足条件的行数 /// public int GetCount(object where) { return MDataTableFilter.GetCount(this, where); } /// /// 根据条件分拆成两个表【满足条件,和非满足条件的】,分出来的数据行和原始表仍是同一个引用 /// public MDataTable[] Split(object where) { return MDataTableFilter.Split(this, where); } #endregion /// /// 加载行(包括行架构)[提示,仅当表为空架构时有效] /// /// internal void LoadRow(MDataRow row) //是否直接能用Row.Table呢??、 { if (this.Columns.Count == 0 && row != null && row.Count > 0) { this.Columns = row.Columns.Clone(); if (!string.IsNullOrEmpty(_TableName) && _TableName.StartsWith("SysDefault")) { _TableName = row.TableName; } _Conn = row.Conn; if (!row[0].IsNullOrEmpty) { NewRow(true).LoadFrom(row); //_Rows.Add(row); } } } /// /// 转换成DataTable /// public DataTable ToDataTable() { DataTable dt = new DataTable(_TableName); if (Columns != null && Columns.Count > 0) { bool checkDuplicate = Columns.CheckDuplicate; List duplicateName = new List(); for (int j = 0; j < Columns.Count; j++) { MCellStruct item = Columns[j]; if (string.IsNullOrEmpty(item.ColumnName)) { item.ColumnName = "Empty_" + item; } if (!checkDuplicate && dt.Columns.Contains(item.ColumnName))//去重。 { string rndName = Guid.NewGuid().ToString(); dt.Columns.Add(rndName, item.ValueType); duplicateName.Add(rndName); continue; } dt.Columns.Add(item.ColumnName, item.ValueType); } int count = dt.Columns.Count; foreach (MDataRow row in Rows) { DataRow dr = dt.NewRow(); for (int i = 0; i < count; i++) { if (row[i].IsNull) { dr[i] = DBNull.Value; } else { dr[i] = row[i].Value; } } dt.Rows.Add(dr); } for (int i = 0; i < duplicateName.Count; i++) { dt.Columns.Remove(duplicateName[i]); } } dt.AcceptChanges(); return dt; } /// /// 输出Xml文档 /// public string ToXml() { return ToXml(false); } public string ToXml(bool isConvertNameToLower) { return ToXml(isConvertNameToLower, true, true); } /// /// 输出Xml文档 /// /// 名称转小写 /// public string ToXml(bool isConvertNameToLower, bool needHeader, bool needRootNode) { StringBuilder xml = new StringBuilder(); if (Columns.Count > 0) { string tableName = string.IsNullOrEmpty(_TableName) ? "Root" : _TableName; string rowName = string.IsNullOrEmpty(_TableName) ? "Row" : _TableName; if (isConvertNameToLower) { tableName = tableName.ToLower(); rowName = rowName.ToLower(); } if (needHeader) { xml.Append(""); } if (needRootNode) { xml.AppendFormat("\r\n<{0}>", tableName); } foreach (MDataRow row in Rows) { xml.AppendFormat("\r\n <{0}>", rowName); foreach (MDataCell cell in row) { xml.Append(cell.ToXml(isConvertNameToLower)); } xml.AppendFormat("\r\n ", rowName); } if (needRootNode) { xml.AppendFormat("\r\n", tableName); } } return xml.ToString(); } public bool WriteXml(string fileName) { return WriteXml(fileName, false); } /// /// 保存Xml /// public bool WriteXml(string fileName, bool isConvertNameToLower) { return IOHelper.Write(fileName, ToXml(isConvertNameToLower), Encoding.UTF8); } /// /// 输出Json /// public string ToJson() { return ToJson(true); } public string ToJson(bool addHead) { return ToJson(addHead, false); } /// 输出头部信息[带count、Success、ErrorMsg](默认true) /// 首行输出表架构信息,反接收时可还原架构(默认false) public string ToJson(bool addHead, bool addSchema) { return ToJson(addHead, addSchema, RowOp.None); } /// 过滤选项 public string ToJson(bool addHead, bool addSchema, RowOp rowOp) { return ToJson(addHead, addSchema, rowOp, false); } public string ToJson(bool addHead, bool addSchema, RowOp rowOp, bool isConvertNameToLower) { return ToJson(addHead, addSchema, rowOp, isConvertNameToLower, JsonHelper.DefaultEscape); } /// 符号转义选项 public string ToJson(bool addHead, bool addSchema, RowOp rowOp, bool isConvertNameToLower, EscapeOp escapeOp) { JsonHelper helper = new JsonHelper(addHead, addSchema); helper.Escape = escapeOp; helper.IsConvertNameToLower = isConvertNameToLower; helper.RowOp = rowOp; helper.Fill(this); bool checkArrayEnd = !addHead && !addSchema; return helper.ToString(checkArrayEnd); } /// /// 输出Json[可指定保存路径] /// public bool WriteJson(bool addHead, bool addSchema, string fileName) { return IOHelper.Write(fileName, ToJson(addHead, addSchema)); } /// /// 将数据表绑定到列表控件 /// /// 列表控件[包括Repeater/DataList/GridView/DataGrid等] public void Bind(object control) { Bind(control, null); } /// /// 将数据表绑定到列表控件 /// /// 列表控件[包括Repeater/DataList/GridView/DataGrid等] /// 当Control为XHtmlAction对象时,需要指定绑定的节点ID public void Bind(object control, string nodeID) { MBindUI.Bind(control, this, nodeID); } /// /// 将新表的行放到原表的下面。 /// /// public void Merge(MDataTable newTable) { if (newTable != null && newTable.Rows.Count > 0) { int count = newTable.Rows.Count;//提前获取总数,是为了避免dt.Merge(dt);//加载自身导致的死循环。 for (int i = 0; i < count; i++) { // _Rows.Add(newTable.Rows[i]); NewRow(true).LoadFrom(newTable.Rows[i]); } } } /// /// 将表里所有行的数据行的状态全部重置 /// /// 状态[0:未更改;1:已赋值,值相同[可插入];2:已赋值,值不同[可更新]] public MDataTable SetState(int state) { SetState(state, BreakOp.None); return this; } /// /// 将表里所有行的数据行的状态全部重置 /// /// 状态[0:未更改;1:已赋值,值相同[可插入];2:已赋值,值不同[可更新]] /// 状态设置选项 public MDataTable SetState(int state, BreakOp op) { if (Rows != null && Rows.Count > 0) { foreach (MDataRow row in Rows) { row.SetState(state, op); } } return this; } /// /// 转实体列表 /// /// 是否使用Emit方式转换[数据越多[大于500条]性能越高],不写默认自适应判断 /// /// public List ToList(params bool[] useEmit) { List list = new List(); if (Rows != null && Rows.Count > 0) { if (((Rows.Count > 500 && useEmit.Length == 0) || (useEmit.Length > 0 && useEmit[0])) && typeof(T).BaseType.Name != "OrmBase")//远程代理实体的属性会变,无法用Emit { FastToT.EmitHandle emit = FastToT.Create(this); foreach (MDataRow row in Rows) { list.Add(emit(row)); } } else { foreach (MDataRow row in Rows) { list.Add(row.ToEntity()); } } } return list; } internal object ToList(Type t) { object listObj = Activator.CreateInstance(t);//创建实例 if (Rows != null && Rows.Count > 0) { Type[] paraTypeList = null; Type listObjType=listObj.GetType(); StaticTool.GetArgumentLength(ref listObjType, out paraTypeList); MethodInfo method = listObjType.GetMethod("Add"); foreach (MDataRow row in Rows) { method.Invoke(listObj, new object[] { row.ToEntity(paraTypeList[0]) }); } } return listObj; } /// /// 批量插入或更新 [提示:操作和当前表名有关,如当前表名不是要提交入库的表名,请给TableName属性重新赋值] /// /// 操作选项[插入|更新] public bool AcceptChanges(AcceptOp op) { return AcceptChanges(op, string.Empty); } /// 操作选项[插入|更新] /// 指定新的数据库链接 /// AcceptOp为Update或Auto时,若需要设置联合主键为唯一检测或更新条件,则可设置多个字段名 public bool AcceptChanges(AcceptOp op, string newConn, params object[] jointPrimaryKeys) { bool result = false; if (Columns.Count == 0 || Rows.Count == 0) { return false;//木有可更新的。 } MDataTableBatchAction action = new MDataTableBatchAction(this, newConn); if ((op & AcceptOp.Truncate) != 0) { action.IsTruncate = true; op = (AcceptOp)(op - AcceptOp.Truncate); } action.SetJoinPrimaryKeys(jointPrimaryKeys); switch (op) { case AcceptOp.Insert: result = action.Insert(false); break; case AcceptOp.InsertWithID: result = action.Insert(true); break; case AcceptOp.Update: result = action.Update(); break; case AcceptOp.Delete: result = action.Delete(); break; case AcceptOp.Auto: result = action.Auto(); break; } if (result && AppConfig.Cache.IsAutoCache) { //取消AOP缓存。 AutoCache.ReadyForRemove(AutoCache.GetBaseKey(action.dalTypeTo, action.database, TableName)); } return result; } /// /// 获取修改过的数据 /// /// public MDataTable GetChanges() { return GetChanges(RowOp.Update); } /// /// 获取修改过的数据(若无修改,则返回Null) /// /// 仅Insert和Update选项可用 /// public MDataTable GetChanges(RowOp rowOp) { MDataTable dt = new MDataTable(_TableName); dt.Columns = Columns; dt.Conn = Conn; dt.DynamicData = DynamicData; dt.joinOnIndex = joinOnIndex; dt.JoinOnName = dt.JoinOnName; dt.RecordsAffected = RecordsAffected; if (this.Rows.Count > 0) { if (rowOp == RowOp.Insert || rowOp == RowOp.Update) { int stateValue = (int)rowOp; foreach (MDataRow row in Rows) { if (row.GetState() >= stateValue) { dt.Rows.Add(row, false); } } } } return dt; } /// /// 返回某列的集合 /// 列名 /// public List GetColumnItems(string columnName) { return GetColumnItems(columnName, BreakOp.None, false); } /// /// 返回某列的集合 /// 列名 /// 参数选项 /// public List GetColumnItems(string columnName, BreakOp op) { return GetColumnItems(columnName, op, false); } /// /// 返回某列的集合 /// /// 列的类型 /// 列名 /// 过滤选项 /// 是否去掉重复数据 public List GetColumnItems(string columnName, BreakOp op, bool isDistinct) { int index = -1; if (Columns != null) { index = Columns.GetIndex(columnName); } return GetColumnItems(index, op, isDistinct); } /// /// 返回某列的集合 /// /// 列的类型 /// 第N列 public List GetColumnItems(int columnIndex) { return GetColumnItems(columnIndex, BreakOp.None); } /// /// 返回某列的集合 /// /// 列的类型 /// 第N列 /// 过滤选项 /// public List GetColumnItems(int columnIndex, BreakOp op) { return GetColumnItems(columnIndex, op, false); } /// /// 返回某列的集合 /// /// 列的类型 /// 第N列 /// 过滤选项 /// 是否去掉重复数据 public List GetColumnItems(int columnIndex, BreakOp op, bool isDistinct) { List items = new List(); if (Columns != null && Rows != null && Rows.Count > 0) { if (columnIndex > -1) { MDataCell cell; foreach (MDataRow row in Rows) { cell = row[columnIndex]; switch (op) { case BreakOp.Null: if (cell.IsNull) { continue; } break; case BreakOp.Empty: if (cell.StringValue == "") { continue; } break; case BreakOp.NullOrEmpty: if (cell.IsNullOrEmpty) { continue; } break; } T value = row.Get(columnIndex, default(T)); if (!isDistinct || !items.Contains(value)) { items.Add(value); } } } else { Error.Throw(string.Format("Table {0} can not find the column", TableName)); } } return items; } /// /// 复制表 /// public MDataTable Clone() { MDataTable newTable = GetSchema(true); newTable.Conn = Conn; newTable.DynamicData = DynamicData; newTable.RecordsAffected = RecordsAffected; newTable.TableName = TableName; if (_Rows.Count > 0) { foreach (MDataRow oldRow in _Rows) { MDataRow newRow = newTable.NewRow(); newRow.LoadFrom(oldRow); newTable.Rows.Add(newRow, false); } } return newTable; } /// /// 复制表的结构 /// /// 是否克隆表结构 /// public MDataTable GetSchema(bool clone) { MDataTable newTable = new MDataTable(_TableName); if (Columns.Count > 0) { newTable.Columns = clone ? Columns.Clone() : Columns; } newTable.Conn = Conn; return newTable; } /// /// 过滤掉重复的数据行(仅比较基础类型、复杂数据类型仅比较类型名称)。 /// 被过滤的数据集表 /// public void Distinct(out MDataTable filterRows) { filterRows = null; if (Rows.Count > 0) { List rowList = new List(); int cCount = Columns.Count; for (int i = 0; i < Rows.Count; i++) { for (int j = Rows.Count - 1; j >= 0 && j != i; j--)//反序检测。 { int eqCount = 0; for (int k = 0; k < cCount; k++)//比较列 { if (Rows[i][k].StringValue == Rows[j][k].StringValue) { eqCount++; } else { break; } } if (eqCount == cCount) { rowList.Add(Rows[j]); Rows.RemoveAt(j); } } } if (rowList.Count > 0) { filterRows = rowList; } } } /// /// 过滤掉重复的数据行(仅比较基础类型、复杂数据类型仅比较类型名称)。 /// public void Distinct() { MDataTable filterRows; Distinct(out filterRows); filterRows = null; } #endregion public override string ToString() { return TableName; } } public partial class MDataTable : IDataReader, IEnumerable//, IEnumerator { private int _Ptr = -1;//行索引 #region IDataRecord 成员 /// /// 获取列的总数 /// int IDataRecord.FieldCount { get { if (Columns != null) { return Columns.Count; } return 0; } } bool IDataRecord.GetBoolean(int i) { return (bool)_Rows[_Ptr][i].Value; } byte IDataRecord.GetByte(int i) { return (byte)_Rows[_Ptr][i].Value; } long IDataRecord.GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length) { return (byte)_Rows[_Ptr][i].Value; } char IDataRecord.GetChar(int i) { return (char)_Rows[_Ptr][i].Value; } long IDataRecord.GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length) { return (char)_Rows[_Ptr][i].Value; } IDataReader IDataRecord.GetData(int i) { return this; } string IDataRecord.GetDataTypeName(int i) { return "";//绑定的可以不需要返回 //return DataType.GetDbType(Columns[i].SqlType.ToString()).ToString(); } DateTime IDataRecord.GetDateTime(int i) { return (DateTime)_Rows[_Ptr][i].Value; } decimal IDataRecord.GetDecimal(int i) { return (decimal)_Rows[_Ptr][i].Value; } double IDataRecord.GetDouble(int i) { return (double)_Rows[_Ptr][i].Value; } Type IDataRecord.GetFieldType(int i) { return _Columns[i].ValueType; } float IDataRecord.GetFloat(int i) { return (float)_Rows[_Ptr][i].Value; } Guid IDataRecord.GetGuid(int i) { return (Guid)_Rows[_Ptr][i].Value; } short IDataRecord.GetInt16(int i) { return (short)_Rows[_Ptr][i].Value; } int IDataRecord.GetInt32(int i) { return (int)_Rows[_Ptr][i].Value; } long IDataRecord.GetInt64(int i) { return (long)_Rows[_Ptr][i].Value; } string IDataRecord.GetName(int i) { return _Columns[i].ColumnName; } int IDataRecord.GetOrdinal(string name) { return _Columns.GetIndex(name); } string IDataRecord.GetString(int i) { return Convert.ToString(_Rows[_Ptr][i].Value); } object IDataRecord.GetValue(int i) { return _Rows[_Ptr][i].Value; } int IDataRecord.GetValues(object[] values) { for (int i = 0; i < values.Length; i++) { values[i] = _Rows[_Ptr][i].Value; } return values.Length; } bool IDataRecord.IsDBNull(int i) { return _Rows[_Ptr][i].IsNull; } object IDataRecord.this[string name] { get { return _Rows[_Ptr][name]; } } object IDataRecord.this[int i] { get { return _Rows[i]; } } #endregion #region IDataReader 成员 /// /// 清除所有行 /// void IDataReader.Close() { _Rows.Clear(); } /// /// 获取数据行总数 /// int IDataReader.Depth { get { if (_Rows != null) { return _Rows.Count; } return 0; } } DataTable IDataReader.GetSchemaTable() { return ToDataTable(); } /// /// 是否已读取完所所有数据,并清空了记录。 /// bool IDataReader.IsClosed { get { return _Rows.Count == 0 && _Ptr >= _Rows.Count - 1; } } /// /// 是否还有下一条数据 /// /// bool IDataReader.NextResult() { return _Ptr < _Rows.Count - 1; } /// /// 索引移到下一条,准备进行读取。 /// bool IDataReader.Read() { if (_Ptr < _Rows.Count - 1) { _Ptr++; return true; } else { _Ptr = -1; return false; } } private int _RecordsAffected; /// /// 返回(查询时)记录总数。 /// public int RecordsAffected { get { if (_RecordsAffected == 0) { return _Rows.Count; } return _RecordsAffected; } set { _RecordsAffected = value; } } #endregion #region IDisposable 成员 void IDisposable.Dispose() { _Rows.Clear(); _Rows = null; } #endregion #region IEnumerable 成员 IEnumerator IEnumerable.GetEnumerator() { //for (int i = 0; i < Rows.Count; i++) //{ // yield return Rows[i]; //} return new System.Data.Common.DbEnumerator(this); } #endregion } public partial class MDataTable { #region 静态方法 CreateFrom /// /// 不关闭Sdr(因为外部MProc.ExeMDataTableList还需要使用) /// /// /// internal static MDataTable CreateFrom(DbDataReader sdr) { MDataTable mTable = new MDataTable("SysDefault"); if (sdr != null && sdr.FieldCount > 0) { DataTable dt = null; bool noSchema = OracleDal.clientType == 0; if (!noSchema) { try { dt = sdr.GetSchemaTable(); } catch { noSchema = true; } } #region 读表结构 if (noSchema) //OracleClient 不支持子查询的GetSchemaTable,但ODP.NET是支持的。 { //从DataReader读取表结构,不管有没有数据。 string hiddenFields = "," + AppConfig.DB.HiddenFields.ToLower() + ","; MCellStruct mStruct; for (int i = 0; i < sdr.FieldCount; i++) { string name = sdr.GetName(i); if (string.IsNullOrEmpty(name)) { name = "Empty_" + i; } bool isHiddenField = hiddenFields.IndexOf("," + name + ",", StringComparison.OrdinalIgnoreCase) > -1; if (!isHiddenField) { mStruct = new MCellStruct(name, DataType.GetSqlType(sdr.GetFieldType(i))); mStruct.ReaderIndex = i; mTable.Columns.Add(mStruct); } } } else if (dt != null && dt.Rows.Count > 0) { TableSchema.FixTableSchemaType(sdr, dt); mTable.Columns = TableSchema.GetColumns(dt); mTable.Columns.dalType = DalCreate.GetDalTypeByReaderName(sdr.GetType().Name); } #endregion if (sdr.HasRows) { MDataRow mRecord = null; List errIndex = new List();//SQLite提供的dll不靠谱,sdr[x]类型转不过时,会直接抛异常 while (sdr.Read()) { #region 读数据行 mRecord = mTable.NewRow(true); for (int i = 0; i < mTable.Columns.Count; i++) { MCellStruct ms = mTable.Columns[i]; object value = null; try { if (errIndex.Contains(i)) { value = sdr.GetString(ms.ReaderIndex); } else { value = sdr[ms.ReaderIndex]; } } catch { if (!errIndex.Contains(i)) { errIndex.Add(i); } value = sdr.GetString(ms.ReaderIndex); } if (value == null || value == DBNull.Value) { mRecord[i].Value = DBNull.Value; mRecord[i].State = 0; } else if (Convert.ToString(value) == string.Empty) { mRecord[i].Value = string.Empty; mRecord[i].State = 1; } else { mRecord[i].Value = value; //sdr.GetValue(i); 用此赋值,内部会进行类型转换。 mRecord[i].State = 1;//初始始状态为1 } } #endregion } } } return mTable; } /// /// 从List列表里加载成MDataTable /// /// 实体列表对象 /// public static MDataTable CreateFrom(object entityList, BreakOp op) { MDataTable dt = new MDataTable("SysDefault"); if (entityList != null) { try { bool isObj = true; Type t = entityList.GetType(); if (t.IsGenericType) { #region 处理列头 Type[] types; int len = StaticTool.GetArgumentLength(ref t, out types); if (len == 2)//字典 { dt.Columns.Add("Key", DataType.GetSqlType(types[0])); dt.Columns.Add("Value", DataType.GetSqlType(types[1])); } else { Type objType = types[0]; if ((objType.FullName.StartsWith("System.") && objType.FullName.Split('.').Length == 2) || objType.IsEnum)//系统类型。 { isObj = false; string name = objType.Name.Split('`')[0]; if (name.StartsWith("Nullable")) { name = Nullable.GetUnderlyingType(objType).Name; } dt.Columns.Add(name, DataType.GetSqlType(objType), false); } else { dt.TableName = objType.Name; dt.Columns = TableSchema.GetColumns(objType); } } #endregion } else if (entityList is Hashtable) { dt.Columns.Add("Key"); dt.Columns.Add("Value"); } else { isObj = false; dt.Columns.Add(t.Name.Replace("[]", ""), SqlDbType.Variant, false); } foreach (object o in entityList as IEnumerable) { MDataRow row = dt.NewRow(); if (isObj) { row.LoadFrom(o, op);//初始值状态为1 } else { row.Set(0, o, 1); } dt.Rows.Add(row); } } catch (Exception err) { Log.WriteLogToTxt(err); } } return dt; } public static MDataTable CreateFrom(object entityList) { return CreateFrom(entityList, BreakOp.None); } public static MDataTable CreateFrom(NameObjectCollectionBase noc) { MDataTable dt = new MDataTable("SysDefault"); if (noc != null) { if (noc is NameValueCollection) { dt.Columns.Add("Key"); dt.Columns.Add("Value"); NameValueCollection nv = noc as NameValueCollection; foreach (string key in nv) { dt.NewRow(true).Set(0, key, 1).Set(1, nv[key], 1); } } else if (noc is HttpCookieCollection) { HttpCookieCollection nv = noc as HttpCookieCollection; dt.Columns.Add("Name"); dt.Columns.Add("Value"); dt.Columns.Add("Expires"); dt.Columns.Add("Domain"); dt.Columns.Add("HttpOnly"); dt.Columns.Add("Path"); for (int i = 0; i < nv.Count; i++) { HttpCookie cookie = nv[i]; dt.NewRow(true).Set(0, cookie.Name).Set(1, cookie.Value) .Set(2, cookie.Expires) .Set(3, cookie.Domain) .Set(4, cookie.HttpOnly) .Set(5, cookie.Path); } } else { dt = CreateFrom(noc as IEnumerable); } } return dt; } /// /// 从Json或Xml字符串反加载成MDataTable /// public static MDataTable CreateFrom(string jsonOrXml) { return CreateFrom(jsonOrXml, null); } public static MDataTable CreateFrom(string jsonOrXml, MDataColumn mdc) { return CreateFrom(jsonOrXml, mdc, JsonHelper.DefaultEscape); } /// /// 从Json或Xml字符串反加载成MDataTable /// public static MDataTable CreateFrom(string jsonOrXml, MDataColumn mdc,EscapeOp op) { if (!string.IsNullOrEmpty(jsonOrXml)) { if (jsonOrXml[0] == '<' || jsonOrXml.EndsWith(".xml")) { return CreateFromXml(jsonOrXml, mdc); } else { return JsonHelper.ToMDataTable(jsonOrXml, mdc,op); } } return new MDataTable(); } internal static MDataTable CreateFromXml(string xmlOrFileName, MDataColumn mdc) { MDataTable dt = new MDataTable(); if (mdc != null) { dt.Columns = mdc; } if (string.IsNullOrEmpty(xmlOrFileName)) { return dt; } xmlOrFileName = xmlOrFileName.Trim(); XmlDocument doc = new XmlDocument(); bool loadOk = false; if (!xmlOrFileName.StartsWith("<"))//可能是文件路径 { dt.TableName = Path.GetFileNameWithoutExtension(xmlOrFileName); dt.Columns = MDataColumn.CreateFrom(xmlOrFileName, false); if (File.Exists(xmlOrFileName)) { try { doc.Load(xmlOrFileName); loadOk = true; } catch { } } } else // xml 字符串 { try { doc.LoadXml(xmlOrFileName); loadOk = true; } catch { } } if (loadOk) { if (doc.DocumentElement.ChildNodes.Count > 0) { dt.TableName = doc.DocumentElement.Name; if (dt.Columns.Count == 0) { //初如化表架构 bool useChildToGetSchema = doc.DocumentElement.ChildNodes[0].ChildNodes.Count > 0; foreach (XmlNode item in doc.DocumentElement.ChildNodes) { if (useChildToGetSchema) { if (item.ChildNodes.Count > 0)//带子节点,用子节点的名称当字段 { foreach (XmlNode child in item.ChildNodes) { if (!dt.Columns.Contains(child.Name)) { dt.Columns.Add(child.Name); } } } } else//不带子节点,用当前节点的属性当字段 { if (item.Attributes != null && item.Attributes.Count > 0)//带子节点,用子节点的名称当字段 { foreach (XmlAttribute attr in item.Attributes) { if (!dt.Columns.Contains(attr.Name)) { dt.Columns.Add(attr.Name); } } } } } } } MDataRow dr = null; foreach (XmlNode row in doc.DocumentElement.ChildNodes) { dr = dt.NewRow(); if (row.ChildNodes.Count > 0)//用子节点处理 { foreach (XmlNode cell in row.ChildNodes) { if (!cell.InnerXml.StartsWith(" 0) //用属性处理 { foreach (XmlAttribute cell in row.Attributes) { dr.Set(cell.Name, cell.Value.Trim(), 1); } dt.Rows.Add(dr); } } } return dt; } #endregion #region 列的取值:Min、Max、Sum、Avg private T GetMinMaxValue(int index, bool isMin) { if (Columns != null && index < Columns.Count && Rows != null && Rows.Count > 0) { List itemList = GetColumnItems(index, BreakOp.NullOrEmpty); if (itemList.Count > 0) { itemList.Sort(); return isMin ? itemList[0] : itemList[itemList.Count - 1]; } } return default(T); } /// /// 获取列的最小值 /// /// 类型 /// 列名 /// public T Min(string columnName) { return GetMinMaxValue(Columns.GetIndex(columnName), true); } /// /// 获取列的最小值 /// /// 类型 /// 列索引 /// public T Min(int index) { return GetMinMaxValue(index, true); } /// /// 获取列的最大值 /// /// 类型 /// 列名 /// public T Max(string columnName) { return GetMinMaxValue(Columns.GetIndex(columnName), false); } /// /// 获取列的最大值 /// /// 类型 /// 列索引 /// public T Max(int index) { return GetMinMaxValue(index, false); } /// /// 汇总某列的值 /// /// 类型 /// 列名 /// public T Sum(string columnName) { return Sum(Columns.GetIndex(columnName)); } /// /// 汇总某列的值 /// /// 类型 /// 列索引 /// public T Sum(int index) { if (Columns != null && index < Columns.Count && Rows != null && Rows.Count > 0) { List itemList = GetColumnItems(index, BreakOp.NullOrEmpty); if (itemList.Count > 0) { Decimal sum = 0; for (int i = 0; i < itemList.Count; i++) { sum += itemList[i]; } return (T)StaticTool.ChangeType(sum, typeof(T)); } } return default(T); } /// /// 记算某列的平均值 /// /// 类型 /// 列名 /// public T Avg(string columnName) { return Avg(Columns.GetIndex(columnName)); } /// ///记算某列的平均值 /// /// 类型 /// 列索引 /// public T Avg(int index) { Decimal sum = Sum(index); if (sum > 0) { return (T)StaticTool.ChangeType(sum / Rows.Count, typeof(T)); } return default(T); } /// /// 行转换列(不指定时,默认取最后三列处理) /// public MDataTable Pivot() { if (Columns.Count < 3) { Error.Throw("At least three columns when call Pivot()"); } int count = Columns.Count; return Pivot(Columns[count - 3].ColumnName, Columns[count - 2].ColumnName, Columns[count - 1].ColumnName); } /// /// 行转换列 /// /// 用于指定行的列名 /// 用于分拆成列的列名 /// 用于显示值的列名 /// public MDataTable Pivot(string rowName, string colName, string valueName) { MDataTable dt = new MDataTable(TableName); #region 处理列头 List colNameItems = GetColumnItems(colName, BreakOp.NullOrEmpty, true); if (colNameItems == null || colNameItems.Count == 0 || colNameItems.Count > 255) { return dt; } dt.Columns.Add(rowName); for (int i = 0; i < colNameItems.Count; i++) { dt.Columns.Add(colNameItems[i]); } #endregion #region 处理数据 List rowNameItems = GetColumnItems(rowName, BreakOp.None, true); MDataTable splitTable = this; for (int i = 0; i < rowNameItems.Count; i++) { MDataRow nameRow = dt.NewRow(true).Set(0, rowNameItems[i]);//新表的一行 MDataTable[] dt2 = splitTable.Split(rowName + "='" + rowNameItems[i] + "'");//筛选分隔 splitTable = dt2[1];//剩下的作为下次分隔 foreach (MDataRow row in dt2[0].Rows)//填写数据 { if (!row[colName].IsNullOrEmpty)//列名不能为空或Null { nameRow.Set(row[colName].Value, row[valueName].Value); } } } #endregion return dt; } #endregion //给MDataTableBatchAction的批量更新使用。 internal void Load(MDataTable dt, MCellStruct primary) { if (dt == null || dt.Rows.Count == 0) { return; } string pkName = primary != null ? primary.ColumnName : Columns.FirstPrimary.ColumnName; int i1 = Columns.GetIndex(pkName); MDataRow rowA, rowB; for (int i = 0; i < Rows.Count; i++) { rowA = Rows[i]; rowB = dt.FindRow(pkName + "='" + rowA[i1].StringValue + "'"); if (rowB != null) { rowA.LoadFrom(rowB, RowOp.IgnoreNull, false); } } } #region 注释掉代码 /* * /// /// 从List列表里加载成MDataTable /// /// 实体列表 /// public static MDataTable LoadFromList(List entityList) where T : class { MDataTable dt = new MDataTable("Default"); if (entityList != null && entityList.Count > 0) { dt.Columns = SchemaCreate.GetColumns(entityList[0].GetType()); //生成表结构。 foreach (T entity in entityList) { MDataRow row = dt.NewRow(); row.LoadFrom(entity); dt.Rows.Add(row); } } return dt; } /// /// 快速创建表架构(无ID列名时,系统自动创建自增型的ID列到首列。) /// /// 文件名 /// 指定的文件存在时,是否允许复盖 /// 创建的列名 /// 列名对应的数据类型(不指定则默认为nvarchar) public static void CreateSchema(string fileName, bool overwrite, string[] columnNames, params SqlDbType[] sqlDbTypes) { if (columnNames.Length >= 0) { if (fileName[1] != ':') { fileName = AppConfig.WebRootPath + fileName; } fileName = fileName.Replace(Path.GetExtension(fileName), string.Empty) + ".ts"; if (!File.Exists(fileName) || overwrite) { MDataColumn mdc = new MDataColumn(); string columnName = string.Empty; for (int i = 0; i < columnNames.Length; i++) { columnName = columnNames[i]; if (sqlDbTypes != null && sqlDbTypes.Length > i) { mdc.Add(columnName, sqlDbTypes[i]); } else { mdc.Add(columnName); } } if (mdc[0].ColumnName.ToLower() != "id") { MCellStruct cellStruct = new MCellStruct("ID", SqlDbType.Int, true, false, -1); cellStruct.IsPrimaryKey = true; mdc.Insert(0, cellStruct); } else if (mdc[0].SqlType == SqlDbType.Int) { mdc[0].IsAutoIncrement = true; mdc[0].IsPrimaryKey = true; } mdc.WriteSchema(fileName); } } } * */ #endregion } }