292 lines
10 KiB
C#
Raw Normal View History

2024-10-22 09:28:58 +08:00
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;
}
}
}