tijian_tieying/web/cyqdata-master/Table/MDataColumn.cs
2025-02-20 12:14:39 +08:00

753 lines
23 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
{
/// <summary>
/// 头列表集合
/// </summary>
public partial class MDataColumn
{
List<MCellStruct> structList;
internal MDataTable _Table;
internal MDataColumn(MDataTable table)
{
structList = new List<MCellStruct>();
_Table = table;
}
public MDataColumn()
{
structList = new List<MCellStruct>();
}
/// <summary>
/// 列名是否变更
/// </summary>
internal bool IsColumnNameChanged = false;
/// <summary>
/// 存储列名的索引
/// </summary>
private MDictionary<string, int> columnIndex = new MDictionary<string, int>(StringComparer.OrdinalIgnoreCase);
/// <summary>
/// 添加列时,检测名称是否重复(默认为true)。
/// </summary>
public bool CheckDuplicate = true;
/// <summary>
/// 隐式转换列头
/// </summary>
/// <param name="columns"></param>
/// <returns></returns>
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;
}
}
/// <summary>
/// 架构所引用的表
/// </summary>
public MDataTable Table
{
get
{
return _Table;
}
}
private string _Description = string.Empty;
/// <summary>
/// 表名描述
/// </summary>
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;
}
/// <summary>
/// 获取列所在的索引位置(若不存在返回-1
/// </summary>
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;
}
/// <summary>
/// 将 列 的序号或位置更改为指定的序号或位置。
/// </summary>
/// <param name="columnName">列名</param>
/// <param name="ordinal">序号</param>
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<object> items = _Table.GetColumnItems<object>(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();
}
/// <summary>
/// 输出Json格式的表构架
/// </summary>
public string ToJson(bool isFullSchema)
{
JsonHelper helper = new JsonHelper();
helper.Fill(this, isFullSchema);
return helper.ToString();
}
/// <summary>
/// 转成行
/// </summary>
/// <param name="tableName">表名</param>
/// <returns></returns>
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;
}
/// <summary>
/// 保存表架构到外部文件中(json格式
/// </summary>
public bool WriteSchema(string fileName)
{
string schema = ToJson(true).Replace("},{", "},\r\n{");//写入文本时要换行。
return IOHelper.Write(fileName, schema);
}
private List<MCellStruct> _JointPrimary = new List<MCellStruct>();
/// <summary>
/// 联合主键
/// </summary>
public List<MCellStruct> 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;
}
}
/// <summary>
/// 第一个主键
/// </summary>
public MCellStruct FirstPrimary
{
get
{
if (JointPrimary.Count > 0)
{
return JointPrimary[0];
}
return null;
}
}
/// <summary>
/// 首个唯一键
/// </summary>
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;
}
}
/// <summary>
/// 当前的数据库类型。
/// </summary>
internal DalType dalType = DalType.None;
/// <summary>
/// 该结构是否由视图拥有
/// </summary>
internal bool isViewOwner = false;
internal List<string> relationTables = new List<string>();
internal void AddRelateionTableName(string tableName)
{
if (!string.IsNullOrEmpty(tableName) && !relationTables.Contains(tableName))
{
relationTables.Add(tableName);
}
}
/// <summary>
/// 将表结构的数据转成Table显示
/// </summary>
/// <returns></returns>
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<MCellStruct>
{
public int Count
{
get { return structList.Count; }
}
#region Add重载方法
/// <summary>
/// 添加列
/// </summary>
/// <param name="columnName">列名</param>
public void Add(string columnName)
{
Add(columnName, SqlDbType.NVarChar, false, true, -1, false, null);
}
/// <param name="SqlType">列的数据类型</param>
public void Add(string columnName, SqlDbType sqlType)
{
Add(columnName, sqlType, false, true, -1, false, null);
}
/// <param name="isAutoIncrement">是否自增ID列</param>
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);
}
/// <param name="defaultValue">默认值[日期类型请传入SqlValue.GetDate]</param>
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<MCellStruct> 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<MCellStruct>
int IList<MCellStruct>.IndexOf(MCellStruct item)
{
return structList.IndexOf(item);
}
#endregion
#region ICollection<MCellStruct>
void ICollection<MCellStruct>.CopyTo(MCellStruct[] array, int arrayIndex)
{
structList.CopyTo(array, arrayIndex);
}
bool ICollection<MCellStruct>.IsReadOnly
{
get { return false; }
}
#endregion
#region IEnumerable<MCellStruct>
IEnumerator<MCellStruct> IEnumerable<MCellStruct>.GetEnumerator()
{
return structList.GetEnumerator();
}
#endregion
#region IEnumerable
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return structList.GetEnumerator();
}
#endregion
#region ICollection<MCellStruct>
public void Clear()
{
structList.Clear();
}
public bool Contains(MCellStruct item)
{
return structList.Contains(item);
}
#endregion
#region IList<MCellStruct>
/// <summary>
/// ReadOnly
/// </summary>
public MCellStruct this[int index]
{
get
{
return structList[index];
}
set
{
Error.Throw(AppConst.Global_NotImplemented);
}
}
#endregion
}
public partial class MDataColumn
{
/// <summary>
/// 从Json或文件中加载成列信息
/// </summary>
/// <param name="jsonOrFileName">Json或文件完整路径名称</param>
/// <returns></returns>
public static MDataColumn CreateFrom(string jsonOrFileName)
{
return CreateFrom(jsonOrFileName, true);
}
/// <summary>
/// 从Json或文件中加载成列信息
/// </summary>
/// <param name="jsonOrFileName">Json或文件完整路径名称</param>
/// <param name="readTxtOrXml">是否从.txt或.xml文件中读取架构默认为true</param>
/// <returns></returns>
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<string>("ColumnName"),
DataType.GetSqlType(row.Get<string>("SqlType", "string")),
row.Get<bool>("IsAutoIncrement", false),
row.Get<bool>("IsCanNull", false),
row.Get<int>("MaxSize", -1));
cs.Scale = row.Get<short>("Scale");
cs.IsPrimaryKey = row.Get<bool>("IsPrimaryKey", false);
cs.DefaultValue = row.Get<string>("DefaultValue");
//新增属性
cs.TableName = row.Get<string>("TableName");
cs.IsUniqueKey = row.Get<bool>("IsUniqueKey", false);
cs.IsForeignKey = row.Get<bool>("IsForeignKey", false);
cs.FKTableName = row.Get<string>("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;
//}
}
}