using System; using System.Collections.Generic; using System.Text; using System.Data; using CYQ.Data.SQL; using CYQ.Data.Tool; using System.IO; namespace CYQ.Data.Table { /// /// 头列表集合 /// public partial class MDataColumn { List structList; internal MDataTable _Table; internal MDataColumn(MDataTable table) { structList = new List(); _Table = table; } public MDataColumn() { structList = new List(); } /// /// 列名是否变更 /// internal bool IsColumnNameChanged = false; /// /// 存储列名的索引 /// private MDictionary columnIndex = new MDictionary(StringComparer.OrdinalIgnoreCase); /// /// 添加列时,检测名称是否重复(默认为true)。 /// public bool CheckDuplicate = true; /// /// 隐式转换列头 /// /// /// public static implicit operator MDataColumn(DataColumnCollection columns) { if (columns == null) { return null; } MDataColumn mColumns = new MDataColumn(); if (columns.Count > 0) { for (int i = 0; i < columns.Count; i++) { MCellStruct cellStruct = new MCellStruct(columns[i].ColumnName, DataType.GetSqlType(columns[i].DataType), columns[i].ReadOnly, columns[i].AllowDBNull, columns[i].MaxLength); mColumns.Add(cellStruct); } } return mColumns; } public MCellStruct this[string key] { get { int index = GetIndex(key); if (index > -1) { return this[index]; } return null; } } /// /// 架构所引用的表 /// public MDataTable Table { get { return _Table; } } private string _Description = string.Empty; /// /// 表名描述 /// public string Description { get { if (string.IsNullOrEmpty(_Description) && _Table != null) { return _Table.Description; } return _Description; } set { _Description = value; } } public MDataColumn Clone() { MDataColumn mcs = new MDataColumn(); mcs.dalType = dalType; mcs.CheckDuplicate = false; mcs.isViewOwner = isViewOwner; foreach (string item in relationTables) { mcs.AddRelateionTableName(item); } for (int i = 0; i < this.Count; i++) { mcs.Add(this[i].Clone()); } return mcs; } public bool Contains(string columnName) { return GetIndex(columnName) > -1; } /// /// 获取列所在的索引位置(若不存在返回-1) /// public int GetIndex(string columnName) { if (columnIndex.Count == 0 || IsColumnNameChanged || columnIndex.Count != Count) { columnIndex.Clear(); for (int i = 0; i < Count; i++) { columnIndex.Add(this[i].ColumnName.Replace("_", ""), i); } IsColumnNameChanged = false; } if (!string.IsNullOrEmpty(columnName)) { if (columnName.IndexOf('_') > -1) { columnName = columnName.Replace("_", "");//兼容映射处理 } if (columnIndex.ContainsKey(columnName)) { return columnIndex[columnName]; } else { //开启默认前缀检测 string[] items = AppConfig.UI.AutoPrefixs.Split(','); if (items != null && items.Length > 0) { foreach (string item in items) { columnName = columnName.StartsWith(item) ? columnName.Substring(3) : item + columnName; if (columnIndex.ContainsKey(columnName)) { return columnIndex[columnName]; } } } } //for (int i = 0; i < Count; i++) //{ // if (string.Compare(this[i].ColumnName.Replace("_", ""), columnName, StringComparison.OrdinalIgnoreCase) == 0)//第三个参数用StringComparison.OrdinalIgnoreCase比用true快。 // { // return i; // } //} } return -1; } /// /// 将 列 的序号或位置更改为指定的序号或位置。 /// /// 列名 /// 序号 public void SetOrdinal(string columnName, int ordinal) { int index = GetIndex(columnName); if (index > -1 && index != ordinal) { MCellStruct mstruct = this[index]; if (_Table != null && _Table.Rows.Count > 0) { List items = _Table.GetColumnItems(index, BreakOp.None); _Table.Columns.RemoveAt(index); _Table.Columns.Insert(ordinal, mstruct); for (int i = 0; i < items.Count; i++) { _Table.Rows[i].Set(ordinal, items[i]); } items = null; } else { structList.RemoveAt(index);//移除 if (ordinal >= Count) { ordinal = Count; } structList.Insert(ordinal, mstruct); } } columnIndex.Clear(); } /// /// 输出Json格式的表构架 /// public string ToJson(bool isFullSchema) { JsonHelper helper = new JsonHelper(); helper.Fill(this, isFullSchema); return helper.ToString(); } /// /// 转成行 /// /// 表名 /// public MDataRow ToRow(string tableName) { MDataRow row = new MDataRow(this); row.TableName = tableName; row.Columns.CheckDuplicate = CheckDuplicate; row.Columns.dalType = dalType; row.Columns.isViewOwner = isViewOwner; row.Columns.relationTables = relationTables; return row; } /// /// 保存表架构到外部文件中(json格式) /// public bool WriteSchema(string fileName) { string schema = ToJson(true).Replace("},{", "},\r\n{");//写入文本时要换行。 return IOHelper.Write(fileName, schema); } private List _JointPrimary = new List(); /// /// 联合主键 /// public List JointPrimary { get { MCellStruct autoIncrementCell = null; if (_JointPrimary.Count == 0 && this.Count > 0) { foreach (MCellStruct item in this) { if (item.IsPrimaryKey) { _JointPrimary.Add(item); } else if (item.IsAutoIncrement) { autoIncrementCell = item; } } if (_JointPrimary.Count == 0) { if (autoIncrementCell != null) { _JointPrimary.Add(autoIncrementCell); } else { _JointPrimary.Add(this[0]); } } } return _JointPrimary; } } /// /// 第一个主键 /// public MCellStruct FirstPrimary { get { if (JointPrimary.Count > 0) { return JointPrimary[0]; } return null; } } /// /// 首个唯一键 /// public MCellStruct FirstUnique { get { MCellStruct ms = null; foreach (MCellStruct item in this) { if (item.IsUniqueKey) { return item; } else if (ms == null && !item.IsPrimaryKey && DataType.GetGroup(item.SqlType) == 0)//取第一个字符串类型 { ms = item; } } if (ms == null && this.Count > 0) { ms = this[0]; } return ms; } } /// /// 当前的数据库类型。 /// internal DalType dalType = DalType.None; /// /// 该结构是否由视图拥有 /// internal bool isViewOwner = false; internal List relationTables = new List(); internal void AddRelateionTableName(string tableName) { if (!string.IsNullOrEmpty(tableName) && !relationTables.Contains(tableName)) { relationTables.Add(tableName); } } /// /// 将表结构的数据转成Table显示 /// /// public MDataTable ToTable() { string tableName = string.Empty; if (_Table != null) { tableName = _Table.TableName; } MDataTable dt = new MDataTable(tableName); dt.Columns.Add("ColumnName"); dt.Columns.Add("MaxSize"); dt.Columns.Add("Scale"); dt.Columns.Add("IsCanNull"); dt.Columns.Add("IsAutoIncrement"); dt.Columns.Add("SqlType"); dt.Columns.Add("IsPrimaryKey"); dt.Columns.Add("IsUniqueKey"); dt.Columns.Add("IsForeignKey"); dt.Columns.Add("FKTableName"); dt.Columns.Add("DefaultValue"); dt.Columns.Add("Description"); dt.Columns.Add("TableName"); for (int i = 0; i < Count; i++) { MCellStruct ms = this[i]; dt.NewRow(true) .Set(0, ms.ColumnName) .Set(1, ms.MaxSize) .Set(2, ms.Scale) .Set(3, ms.IsCanNull) .Set(4, ms.IsAutoIncrement) .Set(5, ms.SqlType) .Set(6, ms.IsPrimaryKey) .Set(7, ms.IsUniqueKey) .Set(8, ms.IsForeignKey) .Set(9, ms.FKTableName) .Set(10, ms.DefaultValue) .Set(11, ms.Description) .Set(12, ms.TableName); } return dt; } } public partial class MDataColumn : IList { public int Count { get { return structList.Count; } } #region Add重载方法 /// /// 添加列 /// /// 列名 public void Add(string columnName) { Add(columnName, SqlDbType.NVarChar, false, true, -1, false, null); } /// 列的数据类型 public void Add(string columnName, SqlDbType sqlType) { Add(columnName, sqlType, false, true, -1, false, null); } /// 是否自增ID列 public void Add(string columnName, SqlDbType sqlType, bool isAutoIncrement) { Add(columnName, sqlType, isAutoIncrement, !isAutoIncrement, -1, isAutoIncrement, null); } public void Add(string columnName, SqlDbType sqlType, bool isAutoIncrement, bool isCanNull, int maxSize) { Add(columnName, sqlType, isAutoIncrement, isCanNull, maxSize, false, null); } /// 默认值[日期类型请传入SqlValue.GetDate] public void Add(string columnName, SqlDbType sqlType, bool isAutoIncrement, bool isCanNull, int maxSize, bool isPrimaryKey, object defaultValue) { string[] items = columnName.Split(','); foreach (string item in items) { MCellStruct mdcStruct = new MCellStruct(item, sqlType, isAutoIncrement, isCanNull, maxSize); mdcStruct.IsPrimaryKey = isPrimaryKey; mdcStruct.DefaultValue = defaultValue; Add(mdcStruct); } } #endregion public void Add(MCellStruct item) { if (item != null && !this.Contains(item) && (!CheckDuplicate || !Contains(item.ColumnName))) { if (dalType == DalType.None) { dalType = item.DalType; } item.MDataColumn = this; structList.Add(item); if (_Table != null && _Table.Rows.Count > 0) { for (int i = 0; i < _Table.Rows.Count; i++) { if (Count > _Table.Rows[i].Count) { _Table.Rows[i].Add(new MDataCell(ref item)); } } } columnIndex.Clear(); } } //public void AddRange(IEnumerable collection) //{ // AddRange(collection as MDataColumn); //} public void AddRange(MDataColumn items) { if (items.Count > 0) { foreach (MCellStruct item in items) { if (!Contains(item.ColumnName)) { Add(item); } } columnIndex.Clear(); } } public bool Remove(MCellStruct item) { Remove(item.ColumnName); return true; } public void Remove(string columnName) { string[] items = columnName.Split(','); foreach (string item in items) { int index = GetIndex(item); if (index > -1) { RemoveAt(index); columnIndex.Clear(); } } } public void RemoveRange(int index, int count) // 1,4 { for (int i = index; i < index + count; i++) { RemoveAt(i); } } public void RemoveAt(int index) { structList.RemoveAt(index); if (_Table != null) { foreach (MDataRow row in _Table.Rows) { if (row.Count > Count) { row.RemoveAt(index); } } } columnIndex.Clear(); } public void Insert(int index, MCellStruct item) { if (item != null && !this.Contains(item) && (!CheckDuplicate || !Contains(item.ColumnName))) { item.MDataColumn = this; structList.Insert(index, item); if (_Table != null && _Table.Rows.Count > 0) { for (int i = 0; i < _Table.Rows.Count; i++) { if (Count > _Table.Rows[i].Count) { _Table.Rows[i].Insert(index, new MDataCell(ref item)); } } } columnIndex.Clear(); } } public void InsertRange(int index, MDataColumn mdc) { for (int i = mdc.Count; i >= 0; i--) { Insert(index, mdc[i]);//反插 } } #region IList 成员 int IList.IndexOf(MCellStruct item) { return structList.IndexOf(item); } #endregion #region ICollection 成员 void ICollection.CopyTo(MCellStruct[] array, int arrayIndex) { structList.CopyTo(array, arrayIndex); } bool ICollection.IsReadOnly { get { return false; } } #endregion #region IEnumerable 成员 IEnumerator IEnumerable.GetEnumerator() { return structList.GetEnumerator(); } #endregion #region IEnumerable 成员 System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return structList.GetEnumerator(); } #endregion #region ICollection 成员 public void Clear() { structList.Clear(); } public bool Contains(MCellStruct item) { return structList.Contains(item); } #endregion #region IList 成员 /// /// ReadOnly /// public MCellStruct this[int index] { get { return structList[index]; } set { Error.Throw(AppConst.Global_NotImplemented); } } #endregion } public partial class MDataColumn { /// /// 从Json或文件中加载成列信息 /// /// Json或文件(完整路径)名称 /// public static MDataColumn CreateFrom(string jsonOrFileName) { return CreateFrom(jsonOrFileName, true); } /// /// 从Json或文件中加载成列信息 /// /// Json或文件(完整路径)名称 /// 是否从.txt或.xml文件中读取架构(默认为true) /// public static MDataColumn CreateFrom(string jsonOrFileName, bool readTxtOrXml) { MDataColumn mdc = new MDataColumn(); MDataTable dt = null; try { bool isTxtOrXml = false; string json = string.Empty; string exName = Path.GetExtension(jsonOrFileName); switch (exName.ToLower()) { case ".ts": case ".xml": case ".txt": string tsFileName = jsonOrFileName.Replace(exName, ".ts"); if (File.Exists(tsFileName)) { json = IOHelper.ReadAllText(tsFileName); } else if (readTxtOrXml && File.Exists(jsonOrFileName)) { isTxtOrXml = true; if (exName == ".xml") { json = IOHelper.ReadAllText(jsonOrFileName, 0, Encoding.UTF8); } else if (exName == ".txt") { json = IOHelper.ReadAllText(jsonOrFileName); } } break; default: json = jsonOrFileName; break; } if (!string.IsNullOrEmpty(json)) { dt = MDataTable.CreateFrom(json); if (dt.Columns.Count > 0) { if (isTxtOrXml) { mdc = dt.Columns.Clone(); } else { foreach (MDataRow row in dt.Rows) { MCellStruct cs = new MCellStruct( row.Get("ColumnName"), DataType.GetSqlType(row.Get("SqlType", "string")), row.Get("IsAutoIncrement", false), row.Get("IsCanNull", false), row.Get("MaxSize", -1)); cs.Scale = row.Get("Scale"); cs.IsPrimaryKey = row.Get("IsPrimaryKey", false); cs.DefaultValue = row.Get("DefaultValue"); //新增属性 cs.TableName = row.Get("TableName"); cs.IsUniqueKey = row.Get("IsUniqueKey", false); cs.IsForeignKey = row.Get("IsForeignKey", false); cs.FKTableName = row.Get("FKTableName"); mdc.Add(cs); } } } } } catch (Exception err) { Log.WriteLogToTxt(err); } finally { dt = null; } return mdc; } //internal bool AcceptChanges(AcceptOp op) //{ // if (_Table == null) // { // return false; // } // return AcceptChanges(op, _Table.TableName, _Table.Conn); //} //internal bool AcceptChanges(AcceptOp op, string tableName, string newConn) //{ // if (string.IsNullOrEmpty(tableName) || string.IsNullOrEmpty(newConn) || Count == 0) // { // return false; // } // return true; //} } }