292 lines
10 KiB
C#
292 lines
10 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Data;
|
|
using System.Linq;
|
|
using System.Xml.Linq;
|
|
|
|
namespace JiShe.CollectBus.Common.Extensions
|
|
{
|
|
public static class DataTableExtensions
|
|
{
|
|
|
|
/// <summary>Converts to list.</summary>
|
|
/// <typeparam name="T"></typeparam>
|
|
/// <param name="dt">The dt.</param>
|
|
/// <returns>
|
|
/// <br />
|
|
/// </returns>
|
|
[Description("转换为列表")]
|
|
public static IList<T> ToList<T>(this DataTable dt) where T : class
|
|
{
|
|
IList<T> list = new List<T>();
|
|
foreach (DataRow dr in dt.Rows)
|
|
{
|
|
T t = Activator.CreateInstance<T>();
|
|
var props = typeof(T).GetProperties();
|
|
foreach (var pro in props)
|
|
{
|
|
var tempName = pro.Name;
|
|
if (!dt.Columns.Contains(tempName)) continue;
|
|
if (!pro.CanWrite) continue;
|
|
var value = dr[tempName];
|
|
if (value != DBNull.Value)
|
|
pro.SetValue(t, value, null);
|
|
}
|
|
|
|
list.Add(t);
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
/// <summary>Converts to data table.</summary>
|
|
/// <typeparam name="T"></typeparam>
|
|
/// <param name="source">The source.</param>
|
|
/// <returns>
|
|
/// <br />
|
|
/// </returns>
|
|
[Description("转换为DataTable")]
|
|
public static DataTable ToDataTable<T>(this ICollection<T> source)
|
|
{
|
|
var props = typeof(T).GetProperties();
|
|
var dt = new DataTable();
|
|
dt.Columns.AddRange(props.Select(p =>
|
|
new DataColumn(p.Name,
|
|
(p.PropertyType.IsGenericType) && (p.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
|
|
? p.PropertyType.GetGenericArguments()[0]
|
|
: p.PropertyType)).ToArray());
|
|
|
|
for (var i = 0; i < source.Count; i++)
|
|
{
|
|
var tempList = new ArrayList();
|
|
foreach (var obj in props.Select(pi => pi.GetValue(source.ElementAt(i), null))) tempList.Add(obj);
|
|
var array = tempList.ToArray();
|
|
dt.LoadDataRow(array, true);
|
|
}
|
|
|
|
return dt;
|
|
}
|
|
|
|
/// <summary>Converts to xml.</summary>
|
|
/// <param name="dt">The dt.</param>
|
|
/// <param name="rootName">Name of the root.</param>
|
|
/// <returns>
|
|
/// <br />
|
|
/// </returns>
|
|
[Description("转换为Xml")]
|
|
public static XDocument ToXml(this DataTable dt, string rootName)
|
|
{
|
|
var xdoc = new XDocument
|
|
{
|
|
Declaration = new XDeclaration("1.0", "utf-8", "")
|
|
};
|
|
xdoc.Add(new XElement(rootName));
|
|
foreach (DataRow row in dt.Rows)
|
|
{
|
|
var element = new XElement(dt.TableName);
|
|
foreach (DataColumn col in dt.Columns)
|
|
{
|
|
element.Add(new XElement(col.ColumnName, row[col].ToString().Trim(' ')));
|
|
}
|
|
xdoc.Root?.Add(element);
|
|
}
|
|
|
|
return xdoc;
|
|
}
|
|
|
|
/// <summary>
|
|
/// "SELECT DISTINCT" over a DataTable
|
|
/// </summary>
|
|
/// <param name="sourceTable">Input DataTable</param>
|
|
/// <param name="fieldName">Field to select (distinct)</param>
|
|
/// <returns></returns>
|
|
[Description("在DataTable中'SELECT DISTINCT'")]
|
|
public static DataTable SelectDistinct(this DataTable sourceTable, string fieldName)
|
|
{
|
|
return SelectDistinct(sourceTable, fieldName, string.Empty);
|
|
}
|
|
|
|
/// <summary>
|
|
/// "SELECT DISTINCT" over a DataTable
|
|
/// </summary>
|
|
/// <param name="sourceTable">Input DataTable</param>
|
|
/// <param name="fieldNames">Fields to select (distinct) Split ','</param>
|
|
/// <param name="filter">Optional filter to be applied to the selection</param>
|
|
/// <returns></returns>
|
|
public static DataTable SelectDistinct(this DataTable sourceTable, string fieldNames, string filter)
|
|
{
|
|
var dt = new DataTable();
|
|
var arrFieldNames = fieldNames.Replace(" ", "").Split(',');
|
|
foreach (var s in arrFieldNames)
|
|
{
|
|
if (sourceTable.Columns.Contains(s))
|
|
dt.Columns.Add(s, sourceTable.Columns[s].DataType);
|
|
else
|
|
throw new Exception($"The column {s} does not exist.");
|
|
}
|
|
|
|
object[] lastValues = null;
|
|
foreach (DataRow dr in sourceTable.Select(filter, fieldNames))
|
|
{
|
|
var newValues = GetRowFields(dr, arrFieldNames);
|
|
if (lastValues == null || !(ObjectComparison(lastValues, newValues)))
|
|
{
|
|
lastValues = newValues;
|
|
dt.Rows.Add(lastValues);
|
|
}
|
|
}
|
|
|
|
return dt;
|
|
}
|
|
|
|
/// <summary>Selects the rows.</summary>
|
|
/// <param name="dt">The dt.</param>
|
|
/// <param name="whereExpression">The where expression.</param>
|
|
/// <param name="orderByExpression">The order by expression.</param>
|
|
/// <returns>
|
|
/// <br />
|
|
/// </returns>
|
|
[Description("查询全部行")]
|
|
public static DataTable SelectRows(this DataTable dt, string whereExpression, string orderByExpression)
|
|
{
|
|
dt.DefaultView.RowFilter = whereExpression;
|
|
dt.DefaultView.Sort = orderByExpression;
|
|
return dt.DefaultView.ToTable();
|
|
}
|
|
|
|
/// <summary>take any DataTable and remove duplicate rows based on any column.</summary>
|
|
/// <param name="dt">The dt.</param>
|
|
/// <param name="keyColName">Name of the key col.</param>
|
|
/// <returns>
|
|
/// <br />
|
|
/// </returns>
|
|
[Description("删除重复的行")]
|
|
public static DataTable Duplicate(this DataTable dt, string keyColName)
|
|
{
|
|
var tblOut = dt.Clone();
|
|
foreach (DataRow row in dt.Rows)
|
|
{
|
|
var found = false;
|
|
var caseIdToTest = row[keyColName].ToString();
|
|
foreach (DataRow row2 in tblOut.Rows)
|
|
{
|
|
if (row2[keyColName].ToString() == caseIdToTest)
|
|
{
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!found)
|
|
tblOut.ImportRow(row);
|
|
}
|
|
return tblOut;
|
|
}
|
|
|
|
/// <summary>Checks if two DataTable objects have the same content.</summary>
|
|
/// <param name="thisDataTable">The this data table.</param>
|
|
/// <param name="otherDataTable">The other data table.</param>
|
|
/// <returns>
|
|
/// <br />
|
|
/// </returns>
|
|
[Description("检查两个DataTable对象是否具有相同的内容")]
|
|
public static bool EqualsByContent(this DataTable thisDataTable, DataTable otherDataTable)
|
|
{
|
|
// Compare row count.
|
|
if (thisDataTable.Rows.Count != otherDataTable.Rows.Count)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Compare column count.
|
|
if (thisDataTable.Columns.Count != otherDataTable.Columns.Count)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Compare data in each cell of each row.
|
|
for (int i = 0; i < thisDataTable.Rows.Count; i++)
|
|
{
|
|
for (int j = 0; j < thisDataTable.Columns.Count; j++)
|
|
{
|
|
if (!thisDataTable.Rows[i][j].Equals(otherDataTable.Rows[i][j]))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
// The two DataTables contain the same data.
|
|
return true;
|
|
}
|
|
|
|
/// <summary>Renames the column.</summary>
|
|
/// <param name="dt">The dt.</param>
|
|
/// <param name="oldName">The old name.</param>
|
|
/// <param name="newName">The new name.</param>
|
|
[Description("重命名列")]
|
|
public static void RenameColumn(this DataTable dt, string oldName, string newName)
|
|
{
|
|
if (dt != null && !string.IsNullOrEmpty(oldName) && !string.IsNullOrEmpty(newName) && oldName != newName)
|
|
{
|
|
int idx = dt.Columns.IndexOf(oldName);
|
|
dt.Columns[idx].ColumnName = newName;
|
|
dt.AcceptChanges();
|
|
}
|
|
}
|
|
|
|
/// <summary>Removes the column.</summary>
|
|
/// <param name="dt">The dt.</param>
|
|
/// <param name="columnName">Name of the column.</param>
|
|
[Description("删除列")]
|
|
public static void RemoveColumn(this DataTable dt, string columnName)
|
|
{
|
|
if (dt != null && !string.IsNullOrEmpty(columnName) && dt.Columns.IndexOf(columnName) >= 0)
|
|
{
|
|
int idx = dt.Columns.IndexOf(columnName);
|
|
dt.Columns.RemoveAt(idx);
|
|
dt.AcceptChanges();
|
|
}
|
|
}
|
|
|
|
private static object[] GetRowFields(DataRow dr, string[] arrFieldNames)
|
|
{
|
|
if (arrFieldNames.Length == 1)
|
|
return new object[] { dr[arrFieldNames[0]] };
|
|
var itemArray = new ArrayList();
|
|
foreach (var field in arrFieldNames)
|
|
itemArray.Add(dr[field]);
|
|
|
|
return itemArray.ToArray();
|
|
}
|
|
|
|
private static bool ObjectComparison(object a, object b)
|
|
{
|
|
if (a == DBNull.Value && b == DBNull.Value) // both are DBNull.Value
|
|
return true;
|
|
if (a == DBNull.Value || b == DBNull.Value) // only one is DBNull.Value
|
|
return false;
|
|
return a.Equals(b); // value type standard comparison
|
|
}
|
|
|
|
private static bool ObjectComparison(IReadOnlyList<object> a, IReadOnlyList<object> b)
|
|
{
|
|
var retValue = true;
|
|
|
|
if (a.Count == b.Count)
|
|
for (var i = 0; i < a.Count; i++)
|
|
{
|
|
if (!ObjectComparison(a[i], b[i]))
|
|
{
|
|
retValue = false;
|
|
break;
|
|
}
|
|
retValue = true;
|
|
}
|
|
|
|
return retValue;
|
|
}
|
|
}
|
|
}
|