327 lines
12 KiB
C#
327 lines
12 KiB
C#
|
|
using CYQ.Data.SQL;
|
|||
|
|
using System;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
using System.Text;
|
|||
|
|
|
|||
|
|
namespace CYQ.Data.Table
|
|||
|
|
{
|
|||
|
|
public partial class MDataTable
|
|||
|
|
{
|
|||
|
|
internal int joinOnIndex = -1;
|
|||
|
|
/// <summary>
|
|||
|
|
/// 用于关联表的列名,不设置时默认取表主键值
|
|||
|
|
/// </summary>
|
|||
|
|
public string JoinOnName
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
if (joinOnIndex > -1)
|
|||
|
|
{
|
|||
|
|
return Columns[joinOnIndex].ColumnName;
|
|||
|
|
}
|
|||
|
|
return string.Empty;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
if (!string.IsNullOrEmpty(value))
|
|||
|
|
{
|
|||
|
|
joinOnIndex = Columns.GetIndex(value);
|
|||
|
|
if (joinOnIndex == -1)
|
|||
|
|
{
|
|||
|
|
Error.Throw("not exist the column name : " + value);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// 两表LeftJoin关联
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="dt">关联表</param>
|
|||
|
|
/// <param name="appendColumns">追加显示的列,没有指定则追加关联表的所有列</param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public MDataTable Join(MDataTable dt, params string[] appendColumns)
|
|||
|
|
{
|
|||
|
|
return MDataTableJoin.Join(this, dt, appendColumns);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 两表LeftJoin关联
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="tableName">关联表名</param>
|
|||
|
|
/// <param name="joinOnName">关联的字段名,设置Null则自动取表主键为关联名</param>
|
|||
|
|
/// <param name="appendColumns">追加显示的列,没有指定则追加关联表的所有列</param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public MDataTable Join(object tableName, string joinOnName, params string[] appendColumns)
|
|||
|
|
{
|
|||
|
|
return MDataTableJoin.Join(this, Convert.ToString(tableName), joinOnName, appendColumns);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// 表间的关联关系
|
|||
|
|
/// </summary>
|
|||
|
|
class MDataTableJoin
|
|||
|
|
{
|
|||
|
|
internal static MDataTable Join(MDataTable dtA, string tableName, string joinOnName, params string[] appendColumns)
|
|||
|
|
{
|
|||
|
|
MDataTable dtB = null;
|
|||
|
|
|
|||
|
|
using (MAction action = new MAction(tableName, dtA.Conn))
|
|||
|
|
{
|
|||
|
|
if (!action.Data.Columns.Contains(joinOnName))
|
|||
|
|
{
|
|||
|
|
joinOnName = action.Data.Columns.FirstPrimary.ColumnName;
|
|||
|
|
}
|
|||
|
|
//action.SetAopState(CYQ.Data.Aop.AopOp.CloseAll);
|
|||
|
|
action.dalHelper.IsAllowRecordSql = false;//屏蔽SQL日志记录 2000数据库大量的In条件会超时。
|
|||
|
|
if (appendColumns.Length > 0)
|
|||
|
|
{
|
|||
|
|
List<string> items = new List<string>(appendColumns.Length + 1);
|
|||
|
|
items.AddRange(appendColumns);
|
|||
|
|
if (!items.Contains(joinOnName))
|
|||
|
|
{
|
|||
|
|
items.Add(joinOnName);
|
|||
|
|
}
|
|||
|
|
action.SetSelectColumns(items.ToArray());
|
|||
|
|
}
|
|||
|
|
string whereIn = SqlCreate.GetWhereIn(action.Data[joinOnName].Struct, dtA.GetColumnItems<string>(dtA.joinOnIndex, BreakOp.NullOrEmpty, true), action.DalType);
|
|||
|
|
dtB = action.Select(whereIn);
|
|||
|
|
dtB.JoinOnName = joinOnName;
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
return Join(dtA, dtB, appendColumns);
|
|||
|
|
}
|
|||
|
|
internal static MDataTable Join(MDataTable dtA, MDataTable dtB, params string[] columns)
|
|||
|
|
{
|
|||
|
|
//记录 ID as PID 映射的列名,中间记录,修改dtB的列名,后面还原
|
|||
|
|
Dictionary<string, string> mapName = new Dictionary<string, string>();
|
|||
|
|
#region 判断条件
|
|||
|
|
int aIndex = dtA.joinOnIndex;
|
|||
|
|
if (aIndex == -1 && dtA.Columns.FirstPrimary != null)
|
|||
|
|
{
|
|||
|
|
aIndex = dtA.Columns.GetIndex(dtA.Columns.FirstPrimary.ColumnName);
|
|||
|
|
}
|
|||
|
|
int bIndex = dtB.joinOnIndex;
|
|||
|
|
if (bIndex == -1 && dtB.Columns.FirstPrimary != null)
|
|||
|
|
{
|
|||
|
|
bIndex = dtB.Columns.GetIndex(dtB.Columns.FirstPrimary.ColumnName);
|
|||
|
|
}
|
|||
|
|
if (aIndex == -1 || bIndex == -1)
|
|||
|
|
{
|
|||
|
|
Error.Throw("set MDataTable's JoinOnName first");
|
|||
|
|
}
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region 构建新表及表结构
|
|||
|
|
MDataTable joinTable = new MDataTable("V_" + dtA.TableName);
|
|||
|
|
joinTable.Columns.AddRange(dtA.Columns.Clone());
|
|||
|
|
if (columns.Length == 0)
|
|||
|
|
{
|
|||
|
|
joinTable.Columns.AddRange(dtB.Columns.Clone());
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
foreach (string column in columns)
|
|||
|
|
{
|
|||
|
|
string[] items = column.Split(' ');
|
|||
|
|
string name = items[0];
|
|||
|
|
MCellStruct ms = null;
|
|||
|
|
if (dtB.Columns.Contains(name))
|
|||
|
|
{
|
|||
|
|
ms = dtB.Columns[name].Clone();
|
|||
|
|
}
|
|||
|
|
if (items.Length > 1)
|
|||
|
|
{
|
|||
|
|
name = items[items.Length - 1];
|
|||
|
|
if (ms == null && dtB.Columns.Contains(name))
|
|||
|
|
{
|
|||
|
|
ms = dtB.Columns[name].Clone();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (ms != null)
|
|||
|
|
{
|
|||
|
|
if (ms.ColumnName != name)
|
|||
|
|
{
|
|||
|
|
dtB.Columns[ms.ColumnName].ColumnName = name;//修改DtB的列名,结尾再还原。
|
|||
|
|
mapName.Add(name, ms.ColumnName);
|
|||
|
|
ms.ColumnName = name;
|
|||
|
|
}
|
|||
|
|
joinTable.Columns.Add(ms);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
List<string> noFind = new List<string>();
|
|||
|
|
Dictionary<string, string> yesFind = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
|||
|
|
string v1 = string.Empty;
|
|||
|
|
MDataRow row, joinRow;
|
|||
|
|
int count = dtB.Rows.Count;
|
|||
|
|
for (int i = 0; i < dtA.Rows.Count; i++)
|
|||
|
|
{
|
|||
|
|
row = dtA.Rows[i];
|
|||
|
|
if (count == 0 || row[aIndex].IsNullOrEmpty || noFind.Contains(row[aIndex].StringValue))
|
|||
|
|
{
|
|||
|
|
joinRow = joinTable.NewRow(true);
|
|||
|
|
joinRow.LoadFrom(row);//后载加A表(同名则复盖)
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
v1 = row[aIndex].StringValue;
|
|||
|
|
if (yesFind.ContainsKey(v1)) // 找到已匹配的数据
|
|||
|
|
{
|
|||
|
|
string[] items = yesFind[v1].Split(',');
|
|||
|
|
foreach (string item in items)
|
|||
|
|
{
|
|||
|
|
joinRow = joinTable.NewRow(true);
|
|||
|
|
joinRow.LoadFrom(dtB.Rows[int.Parse(item)]);//先加载B表
|
|||
|
|
joinRow.LoadFrom(row);//后载加A表(同名则复盖)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
bool isFind = false;
|
|||
|
|
for (int j = 0; j < dtB.Rows.Count; j++)
|
|||
|
|
{
|
|||
|
|
if (v1 == dtB.Rows[j][bIndex].StringValue)//找到
|
|||
|
|
{
|
|||
|
|
joinRow = joinTable.NewRow(true);
|
|||
|
|
joinRow.LoadFrom(dtB.Rows[j]);//先加载B表
|
|||
|
|
joinRow.LoadFrom(row);//后载加A表(同名则复盖)
|
|||
|
|
isFind = true;
|
|||
|
|
if (yesFind.ContainsKey(v1))
|
|||
|
|
{
|
|||
|
|
yesFind[v1] = yesFind[v1] + "," + j;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
yesFind.Add(v1, j.ToString());
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (!isFind)
|
|||
|
|
{
|
|||
|
|
noFind.Add(v1);
|
|||
|
|
joinRow = joinTable.NewRow(true);//找不到时,只加载A表。
|
|||
|
|
joinRow.LoadFrom(row);//后载加A表(同名则复盖)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
//还原DtB的列
|
|||
|
|
if (mapName.Count > 0)
|
|||
|
|
{
|
|||
|
|
foreach (KeyValuePair<string,string> item in mapName)
|
|||
|
|
{
|
|||
|
|
dtB.Columns[item.Key].ColumnName = item.Value;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
#region 注销临时变量
|
|||
|
|
noFind.Clear();
|
|||
|
|
noFind = null;
|
|||
|
|
yesFind.Clear();
|
|||
|
|
yesFind = null;
|
|||
|
|
mapName = null;
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
return joinTable;
|
|||
|
|
}
|
|||
|
|
#region 匹配单条数据 已注释
|
|||
|
|
/*
|
|||
|
|
internal static MDataTable Join(MDataTable dtA, MDataTable dtB, params string[] columns)
|
|||
|
|
{
|
|||
|
|
#region 判断条件
|
|||
|
|
int aIndex = dtA.joinOnIndex;
|
|||
|
|
if (aIndex == -1 && dtA.Columns.FirstPrimary != null)
|
|||
|
|
{
|
|||
|
|
aIndex = dtA.Columns.GetIndex(dtA.Columns.FirstPrimary.ColumnName);
|
|||
|
|
}
|
|||
|
|
int bIndex = dtB.joinOnIndex;
|
|||
|
|
if (bIndex == -1 && dtB.Columns.FirstPrimary != null)
|
|||
|
|
{
|
|||
|
|
bIndex = dtB.Columns.GetIndex(dtB.Columns.FirstPrimary.ColumnName);
|
|||
|
|
}
|
|||
|
|
if (aIndex == -1 || bIndex == -1)
|
|||
|
|
{
|
|||
|
|
Error.Throw("set MDataTable's JoinOnName first");
|
|||
|
|
}
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region 构建新表及表结构
|
|||
|
|
MDataTable joinTable = new MDataTable("V_" + dtA.TableName);
|
|||
|
|
joinTable.Columns.AddRange(dtA.Columns.Clone());
|
|||
|
|
|
|||
|
|
Dictionary<string, int> keyValue = new Dictionary<string, int>();
|
|||
|
|
if (columns.Length == 0)
|
|||
|
|
{
|
|||
|
|
joinTable.Columns.AddRange(dtB.Columns.Clone());
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
foreach (string column in columns)
|
|||
|
|
{
|
|||
|
|
if (dtB.Columns.Contains(column))
|
|||
|
|
{
|
|||
|
|
joinTable.Columns.Add(dtB.Columns[column].Clone());
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
string v1 = string.Empty;
|
|||
|
|
MDataRow row, joinRow;
|
|||
|
|
MDataCell cell;
|
|||
|
|
int count = dtB.Rows.Count;
|
|||
|
|
for (int i = 0; i < dtA.Rows.Count; i++)
|
|||
|
|
{
|
|||
|
|
joinRow = joinTable.NewRow(true);
|
|||
|
|
row = dtA.Rows[i];
|
|||
|
|
if (count > 0)
|
|||
|
|
{
|
|||
|
|
cell = dtA.Rows[i][aIndex];
|
|||
|
|
if (!cell.IsNullOrEmpty)
|
|||
|
|
{
|
|||
|
|
v1 = cell.strValue;
|
|||
|
|
if (keyValue.ContainsKey(v1)) // 找到已匹配的数据
|
|||
|
|
{
|
|||
|
|
if (keyValue[v1] > -1)
|
|||
|
|
{
|
|||
|
|
joinRow.LoadFrom(dtB.Rows[keyValue[v1]]);//先加载B表
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
bool isFind = false;
|
|||
|
|
for (int j = 0; j < dtB.Rows.Count; j++)
|
|||
|
|
{
|
|||
|
|
if (v1 == dtB.Rows[j][bIndex].strValue)
|
|||
|
|
{
|
|||
|
|
joinRow.LoadFrom(dtB.Rows[j]);
|
|||
|
|
keyValue.Add(v1, j);
|
|||
|
|
isFind = true;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (!isFind)
|
|||
|
|
{
|
|||
|
|
keyValue.Add(v1, -1);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
joinRow.LoadFrom(row);//后载加A表(同名则复盖)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
keyValue.Clear();
|
|||
|
|
keyValue = null;
|
|||
|
|
return joinTable;
|
|||
|
|
}
|
|||
|
|
*/
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
}
|