private void btnAddRelation_Click(Object sender, EventArgs e) { IDataTable table = GetSelectedTable(); if (table == null) { return; } IDataRelation dr = table.CreateRelation(); table.Relations.Add(dr); dgvRelation.DataSource = null; dgvRelation.DataSource = table.Relations; pgColumn.SelectedObject = dr; }
/// <summary>复制数据表到另一个数据表,复制所有数据列、索引和关系</summary> /// <param name="src"></param> /// <param name="des"></param> /// <param name="resetColumnID">是否重置列ID</param> /// <returns></returns> public static IDataTable CopyAllFrom(this IDataTable src, IDataTable des, Boolean resetColumnID = false) { src.CopyFrom(des); src.Columns.AddRange(des.Columns.Select(i => src.CreateColumn().CopyFrom(i))); src.Indexes.AddRange(des.Indexes.Select(i => src.CreateIndex().CopyFrom(i))); src.Relations.AddRange(des.Relations.Select(i => src.CreateRelation().CopyFrom(i))); // 重载ID //if (resetColumnID) src.Columns.ForEach((it, i) => it.ID = i + 1); if (resetColumnID) { for (int i = 0; i < src.Columns.Count; i++) { src.Columns[i].ID = i + 1; } } return(src); }
/// <summary>猜测表间关系</summary> /// <param name="table"></param> /// <param name="rtable"></param> /// <param name="rname"></param> /// <param name="column"></param> /// <param name="name"></param> /// <returns></returns> public virtual Boolean GuessRelation(IDataTable table, IDataTable rtable, String rname, IDataColumn column, String name) { if (name.Length <= rtable.Name.Length || !name.StartsWith(rtable.Name, StringComparison.OrdinalIgnoreCase)) return false; var key = name.Substring(rtable.Name.Length); var dc = rtable.GetColumn(key); // 猜测两表关联关系时,两个字段的类型也必须一致 if (dc == null || dc.DataType != column.DataType) return false; // 建立关系 var dr = table.CreateRelation(); dr.Column = column.Name; dr.RelationTable = rtable.Name; dr.RelationColumn = dc.Name; // 表关系这里一般是多对一,比如管理员的RoleID=>Role+Role.ID,对于索引来说,不是唯一的 dr.Unique = false; // 当然,如果这个字段column有唯一索引,那么,这里也是唯一的。这就是典型的一对一 if (column.PrimaryKey || column.Identity) dr.Unique = true; else { var di = table.GetIndex(column.Name); if (di != null && di.Unique) dr.Unique = true; } dr.Computed = true; if (table.GetRelation(dr) == null) table.Relations.Add(dr); // 给另一方建立关系 //foreach (IDataRelation item in rtable.Relations) //{ // if (item.Column == dc.Name && item.RelationTable == table.Name && item.RelationColumn == column.Name) return dr; //} if (rtable.GetRelation(dc.Name, table.Name, column.Name) != null) return true; dr = rtable.CreateRelation(); dr.Column = dc.Name; dr.RelationTable = table.Name; dr.RelationColumn = column.Name; // 那么这里就是唯一的啦 dr.Unique = true; // 当然,如果字段dc不是主键,也没有唯一索引,那么关系就不是唯一的。这就是典型的多对多 if (!dc.PrimaryKey && !dc.Identity) { var di = rtable.GetIndex(dc.Name); // 没有索引,或者索引不是唯一的 if (di == null || !di.Unique) dr.Unique = false; } dr.Computed = true; if (rtable.GetRelation(dr) == null) rtable.Relations.Add(dr); return true; }
/// <summary>读取</summary> /// <param name="table"></param> /// <param name="reader"></param> /// <returns></returns> public static IDataTable ReadXml(this IDataTable table, XmlReader reader) { // 读属性 if (reader.HasAttributes) { reader.MoveToFirstAttribute(); ReadXml(reader, table); } reader.ReadStartElement(); // 读字段 reader.MoveToElement(); // 有些数据表模型没有字段 if (reader.NodeType == XmlNodeType.Element && reader.Name.EqualIgnoreCase("Table")) { return(table); } while (reader.NodeType != XmlNodeType.EndElement) //while (reader.NodeType == XmlNodeType.Element) { switch (reader.Name) { case "Columns": reader.ReadStartElement(); var id = 1; while (reader.IsStartElement()) { var dc = table.CreateColumn(); dc.ID = id++; var v = reader.GetAttribute("DataType"); if (v != null) { dc.DataType = v.GetTypeEx(); v = reader.GetAttribute("Length"); var len = 0; if (v != null && Int32.TryParse(v, out len)) { dc.Length = len; } // 含有ID表示是旧的,不需要特殊处理,否则一些默认值会不对 v = reader.GetAttribute("ID"); if (v == null) { dc = Fix(dc, dc); } } (dc as IXmlSerializable).ReadXml(reader); table.Columns.Add(dc); } reader.ReadEndElement(); // 修正可能的主字段 if (!table.Columns.Any(e => e.Master)) { var f = table.Columns.FirstOrDefault(e => e.Name.EqualIgnoreCase("Name", "Title")); if (f != null) { f.Master = true; } } break; case "Indexes": reader.ReadStartElement(); while (reader.IsStartElement()) { var di = table.CreateIndex(); (di as IXmlSerializable).ReadXml(reader); di.Fix(); table.Indexes.Add(di); } reader.ReadEndElement(); break; case "Relations": reader.ReadStartElement(); while (reader.IsStartElement()) { var dr = table.CreateRelation(); (dr as IXmlSerializable).ReadXml(reader); if (table.GetRelation(dr) == null) { table.Relations.Add(dr); } } reader.ReadEndElement(); break; default: // 这里必须处理,否则加载特殊Xml文件时将会导致死循环 reader.Read(); break; } } //if (reader.NodeType != XmlNodeType.Element && reader.NodeType != XmlNodeType.EndElement) reader.Read(); //reader.ReadEndElement(); if (reader.NodeType == XmlNodeType.EndElement) { reader.ReadEndElement(); } return(table); }
/// <summary>猜测表间关系</summary> /// <param name="table"></param> /// <param name="rtable"></param> /// <param name="rname"></param> /// <param name="column"></param> /// <param name="name">名称</param> /// <returns></returns> public virtual Boolean GuessRelation(IDataTable table, IDataTable rtable, String rname, IDataColumn column, String name) { if (table == null || rtable == null || rname == null || column == null || name == null) { return(false); } if (name.Length <= rtable.TableName.Length || !name.StartsWithIgnoreCase(rtable.TableName)) { return(false); } var key = name.Substring(rtable.TableName.Length); var dc = rtable.GetColumn(key); // 猜测两表关联关系时,两个字段的类型也必须一致 if (dc == null || dc.DataType != column.DataType) { return(false); } // 建立关系 var dr = table.CreateRelation(); dr.Column = column.ColumnName; dr.RelationTable = rtable.TableName; dr.RelationColumn = dc.ColumnName; // 表关系这里一般是多对一,比如管理员的RoleID=>Role+Role.ID,对于索引来说,不是唯一的 dr.Unique = false; // 当然,如果这个字段column有唯一索引,那么,这里也是唯一的。这就是典型的一对一 if (column.PrimaryKey || column.Identity) { dr.Unique = true; } else { var di = table.GetIndex(column.ColumnName); if (di != null && di.Unique) { dr.Unique = true; } } dr.Computed = true; if (table.GetRelation(dr) == null) { table.Relations.Add(dr); } // 给另一方建立关系 if (rtable.GetRelation(dc.ColumnName, table.TableName, column.ColumnName) != null) { return(true); } dr = rtable.CreateRelation(); dr.Column = dc.ColumnName; dr.RelationTable = table.TableName; dr.RelationColumn = column.ColumnName; // 那么这里就是唯一的啦 dr.Unique = true; // 当然,如果字段dc不是主键,也没有唯一索引,那么关系就不是唯一的。这就是典型的多对多 if (!dc.PrimaryKey && !dc.Identity) { var di = rtable.GetIndex(dc.ColumnName); // 没有索引,或者索引不是唯一的 if (di == null || !di.Unique) { dr.Unique = false; } } dr.Computed = true; if (rtable.GetRelation(dr) == null) { rtable.Relations.Add(dr); } return(true); }
/// <summary>读取</summary> /// <param name="table"></param> /// <param name="reader"></param> /// <returns></returns> public static IDataTable ReadXml(this IDataTable table, XmlReader reader) { // 读属性 if (reader.HasAttributes) { reader.MoveToFirstAttribute(); //do //{ // switch (reader.Name) // { // case "ID": // table.ID = reader.ReadContentAsInt(); // break; // case "Name": // table.Name = reader.ReadContentAsString(); // break; // case "Alias": // table.Alias = reader.ReadContentAsString(); // break; // case "Owner": // table.Owner = reader.ReadContentAsString(); // break; // case "DbType": // table.DbType = (DatabaseType)Enum.Parse(typeof(DatabaseType), reader.ReadContentAsString()); // break; // case "IsView": // table.IsView = Boolean.Parse(reader.ReadContentAsString()); // break; // case "Description": // table.Description = reader.ReadContentAsString(); // break; // default: // break; // } //} while (reader.MoveToNextAttribute()); ReadXml(reader, table); } reader.ReadStartElement(); // 读字段 reader.MoveToElement(); while (reader.NodeType != XmlNodeType.EndElement) { switch (reader.Name) { case "Columns": reader.ReadStartElement(); while (reader.IsStartElement()) { var dc = table.CreateColumn(); (dc as IXmlSerializable).ReadXml(reader); table.Columns.Add(dc); } reader.ReadEndElement(); break; case "Indexes": reader.ReadStartElement(); while (reader.IsStartElement()) { var di = table.CreateIndex(); (di as IXmlSerializable).ReadXml(reader); table.Indexes.Add(di); } reader.ReadEndElement(); break; case "Relations": reader.ReadStartElement(); while (reader.IsStartElement()) { var dr = table.CreateRelation(); (dr as IXmlSerializable).ReadXml(reader); if (table.GetRelation(dr) == null) { table.Relations.Add(dr); } } reader.ReadEndElement(); break; default: break; } } //reader.ReadEndElement(); if (reader.NodeType == XmlNodeType.EndElement) { reader.ReadEndElement(); } return(table); }