using System;
using System.Collections.Generic;
using System.Text;
using CYQ.Data.SQL;
using CYQ.Data.Tool;
using System.Data.SqlClient;
using System.Reflection;
using System.Data;
using System.Data.SqlTypes;
using System.IO;
using System.Diagnostics;
//using Oracle.DataAccess.Client;
namespace CYQ.Data.Table
{
///
/// 批量操作。
///
internal partial class MDataTableBatchAction
{
///
/// 联合主键
///
List jointPrimaryIndex;
MDataTable mdt, sourceTable;
internal DalType dalTypeTo = DalType.None;
internal string database = string.Empty;
private bool _IsTruncate;
///
/// Insert前是否先清表
///
public bool IsTruncate
{
get { return _IsTruncate; }
set { _IsTruncate = value; }
}
string _Conn = string.Empty;
///
/// 内部操作对象(需要同一个事务处理)。
///
private DbBase _dalHelper;
public MDataTableBatchAction(MDataTable mTable)
{
Init(mTable, string.Empty);
}
public MDataTableBatchAction(MDataTable mTable, string conn)
{
Init(mTable, conn);
}
private void Init(MDataTable mTable, string conn)
{
if (mTable.Columns == null || mTable.Columns.Count == 0)
{
Error.Throw("MDataTable's columns can't be null or columns'length can't be zero");
}
if (string.IsNullOrEmpty(mTable.TableName))
{
Error.Throw("MDataTable's tablename can't null or empty");
}
mdt = sourceTable = mTable;
if (mdt.TableName.IndexOfAny(new char[] { '(', ')' }) > -1)
{
mdt.TableName = mdt.TableName.Substring(mdt.TableName.LastIndexOf(')') + 1).Trim();
}
if (!string.IsNullOrEmpty(conn))
{
_Conn = conn;
}
else
{
if (mTable.DynamicData != null && mTable.DynamicData is MAction)//尝试多动态中获取链接
{
_Conn = ((MAction)mTable.DynamicData).ConnectionString;
}
else if (mTable.DynamicData != null && mTable.DynamicData is MProc)
{
_Conn = ((MProc)mTable.DynamicData).ConnectionString;
}
else
{
_Conn = mTable.Conn;
}
}
if (!DBTool.ExistsTable(mdt.TableName, _Conn, out dalTypeTo, out database))
{
DBTool.ErrorMsg = null;
if (!DBTool.CreateTable(mdt.TableName, mdt.Columns, _Conn))
{
Error.Throw("Create Table Error:" + mdt.TableName + DBTool.ErrorMsg);
}
}
MDataColumn column = DBTool.GetColumns(mdt.TableName, _Conn);
FixTable(column);//
if (mdt.Columns.Count == 0)
{
Error.Throw("After fix table columns, length can't be zero");
}
SetDbBaseForTransaction();
}
private void SetDbBaseForTransaction()
{
if (mdt.DynamicData != null)
{
if (mdt.DynamicData is MProc)
{
_dalHelper = ((MProc)mdt.DynamicData).dalHelper;
}
else if (mdt.DynamicData is MAction)
{
_dalHelper = ((MAction)mdt.DynamicData).dalHelper;
}
}
}
///
/// 进行列修正(只有移除 和 修正类型,若无主键列,则新增主键列)
///
private void FixTable(MDataColumn column)
{
if (column.Count > 0)
{
bool tableIsChange = false;
for (int i = mdt.Columns.Count - 1; i >= 0; i--)
{
if (!column.Contains(mdt.Columns[i].ColumnName))//没有此列
{
if (!tableIsChange)
{
mdt = mdt.Clone();//列需要变化时,克隆一份,不变更原有数据。
tableIsChange = true;
}
mdt.Columns.RemoveAt(i);
}
else
{
MCellStruct ms = column[mdt.Columns[i].ColumnName];//新表的字段
Type valueType = mdt.Columns[i].ValueType;//存档的字段的值的原始类型。
bool isChangeType = mdt.Columns[i].SqlType != ms.SqlType;
mdt.Columns[i].Load(ms);
if (isChangeType)
{
//修正数据的数据类型。
foreach (MDataRow row in mdt.Rows)
{
row[i].FixValue();//重新自我赋值修正数据类型。
}
}
}
}
//主键检测,若没有,则补充主键
if (column.JointPrimary != null && column.JointPrimary.Count > 0)
{
if (!mdt.Columns.Contains(column[0].ColumnName) && (column[0].IsPrimaryKey || column[0].IsAutoIncrement))
{
MCellStruct ms = column[0].Clone();
mdt = mdt.Clone();//列需要变化时,克隆一份,不变更原有数据。
ms.MDataColumn = null;
mdt.Columns.Insert(0, ms);
}
}
}
}
///
/// 设置联合主键
///
/// 联合主键
internal void SetJoinPrimaryKeys(object[] jointPrimaryKeys)
{
if (jointPrimaryKeys != null && jointPrimaryKeys.Length > 0)
{
int index = -1;
jointPrimaryIndex = new List();
foreach (object o in jointPrimaryKeys) // 检测列名是否存在,不存在则抛异常
{
index = mdt.Columns.GetIndex(Convert.ToString(o));
if (index == -1)
{
Error.Throw("table " + mdt.TableName + " not exist the column name : " + Convert.ToString(o));
}
else
{
if (!jointPrimaryIndex.Contains(index))
{
jointPrimaryIndex.Add(index);
}
}
}
}
}
internal List GetJoinPrimaryCell(MDataRow row)
{
if (jointPrimaryIndex != null && jointPrimaryIndex.Count > 0)
{
List cells = new List(jointPrimaryIndex.Count);
for (int i = 0; i < jointPrimaryIndex.Count; i++)
{
cells.Add(row[jointPrimaryIndex[i]]);
}
return cells;
}
else
{
return row.JointPrimaryCell;
}
}
internal bool Insert(bool keepID)
{
try
{
if (dalTypeTo == DalType.MsSql)
{
return MsSqlBulkCopyInsert(keepID);
}
else if (dalTypeTo == DalType.Oracle && _dalHelper == null && !IsTruncate)
{
if (OracleDal.clientType == 1 && keepID)
{
return OracleBulkCopyInsert();//不支持外部事务合并(因为参数只能传链接字符串。)
}
//else if (IsAllowBulkCopy(DalType.Oracle))
//{
// return LoadDataInsert(dalTypeTo, keepID);
//}
}
else if (dalTypeTo == DalType.MySql && IsAllowBulkCopy(DalType.MySql))
{
return LoadDataInsert(dalTypeTo, keepID);
}
//if (dalTypeTo == DalType.Txt || dalTypeTo == DalType.Xml)
//{
// NoSqlAction.ResetStaticVar();//重置一下缓存
//}
return NomalInsert(keepID);
}
catch (Exception err)
{
if (err.InnerException != null)
{
err = err.InnerException;
}
sourceTable.DynamicData = err;
Log.WriteLogToTxt(err);
return false;
}
}
internal bool Update()
{
bool hasFK = (jointPrimaryIndex != null && jointPrimaryIndex.Count > 1) || mdt.Columns.JointPrimary.Count > 1;
if (!hasFK)
{
foreach (MCellStruct item in mdt.Columns)
{
if ((item.IsForeignKey && string.IsNullOrEmpty(item.FKTableName))
|| item.MaxSize > 8000 || DataType.GetGroup(item.SqlType) == 999)
{
hasFK = true;
break;
}
}
if (!hasFK && !string.IsNullOrEmpty(AppConfig.DB.DeleteField))
{
hasFK = mdt.Columns.Contains(AppConfig.DB.DeleteField);
}
}
if (hasFK)
{
return NormalUpdate();
}
else
{
return BulkCopyUpdate();//只有一个主键,没有外键关联,同时只有基础类型。
}
}
internal bool Auto()
{
bool result = true;
using (MAction action = new MAction(mdt.TableName, _Conn))
{
action.SetAopState(Aop.AopOp.CloseAll);
DbBase sourceHelper = action.dalHelper;
if (_dalHelper != null)
{
action.dalHelper = _dalHelper;
}
else
{
action.BeginTransation();
}
action.dalHelper.IsAllowRecordSql = false;//屏蔽SQL日志记录 2000数据库大量的In条件会超时。
if ((jointPrimaryIndex != null && jointPrimaryIndex.Count == 1) || (jointPrimaryIndex == null && mdt.Columns.JointPrimary.Count == 1))
//jointPrimaryIndex == null && mdt.Columns.JointPrimary.Count == 1 && mdt.Rows.Count <= 10000
//&& (!action.DalVersion.StartsWith("08") || mdt.Rows.Count < 1001)) //只有一个主键-》组合成In远程查询返回数据-》
{
#region 新逻辑
MCellStruct keyColumn = jointPrimaryIndex != null ? mdt.Columns[jointPrimaryIndex[0]] : mdt.Columns.FirstPrimary;
string columnName = keyColumn.ColumnName;
//计算分组处理
int pageSize = 5000;
if (action.DalVersion.StartsWith("08")) { pageSize = 1000; }
int count = mdt.Rows.Count / pageSize + 1;
for (int i = 0; i < count; i++)
{
MDataTable dt = mdt.Select(i + 1, pageSize, null);//分页读取
if (dt != null && dt.Rows.Count > 0)
{
string whereIn = SqlCreate.GetWhereIn(keyColumn, dt.GetColumnItems(columnName, BreakOp.NullOrEmpty, true), action.DalType);
action.SetSelectColumns(columnName);
MDataTable keyTable = action.Select(whereIn);//拿到数据,准备分拆上市
MDataTable[] dt2 = dt.Split(SqlCreate.GetWhereIn(keyColumn, keyTable.GetColumnItems(columnName, BreakOp.NullOrEmpty, true), DalType.None));//这里不需要格式化查询条件。
result = dt2[0].Rows.Count == 0;
if (!result)
{
MDataTable updateTable = dt2[0];
updateTable.SetState(2, BreakOp.Null);
updateTable.DynamicData = action;
result = updateTable.AcceptChanges(AcceptOp.Update, _Conn, columnName);
if (!result)
{
sourceTable.DynamicData = updateTable.DynamicData;
}
}
if (result && dt2[1].Rows.Count > 0)
{
MDataTable insertTable = dt2[1];
insertTable.DynamicData = action;
bool keepID = !insertTable.Rows[0].PrimaryCell.IsNullOrEmpty;
result = insertTable.AcceptChanges((keepID ? AcceptOp.InsertWithID : AcceptOp.Insert), _Conn, columnName);
if (!result)
{
sourceTable.DynamicData = insertTable.DynamicData;
}
}
}
}
#endregion
#region 旧逻辑,已不用 分拆处理 本地比较分拆两个表格【更新和插入】-》分开独立处理。
/*
string columnName = mdt.Columns.FirstPrimary.ColumnName;
string whereIn = SqlCreate.GetWhereIn(mdt.Columns.FirstPrimary, mdt.GetColumnItems(columnName, BreakOp.NullOrEmpty, true), action.DalType);
action.SetSelectColumns(mdt.Columns.FirstPrimary.ColumnName);
dt = action.Select(whereIn);
MDataTable[] dt2 = mdt.Split(SqlCreate.GetWhereIn(mdt.Columns.FirstPrimary, dt.GetColumnItems(columnName, BreakOp.NullOrEmpty, true), DalType.None));//这里不需要格式化查询条件。
result = dt2[0].Rows.Count == 0;
if (!result)
{
dt2[0].SetState(2, BreakOp.Null);
dt2[0].DynamicData = action;
MDataTableBatchAction m1 = new MDataTableBatchAction(dt2[0], _Conn);
m1.SetJoinPrimaryKeys(new string[] { columnName });
result = m1.Update();
if (!result)
{
sourceTable.DynamicData = dt2[0].DynamicData;
}
}
if (result && dt2[1].Rows.Count > 0)
{
dt2[1].DynamicData = action;
MDataTableBatchAction m2 = new MDataTableBatchAction(dt2[1], _Conn);
m2.SetJoinPrimaryKeys(new string[] { columnName });
result = m2.Insert(!dt2[1].Rows[0].PrimaryCell.IsNullOrEmpty);
if (!result)
{
sourceTable.DynamicData = dt2[1].DynamicData;
}
}
*/
#endregion
}
else
{
// action.BeginTransation();
foreach (MDataRow row in mdt.Rows)
{
#region 循环处理
action.ResetTable(row, false);
string where = SqlCreate.GetWhere(action.DalType, GetJoinPrimaryCell(row));
bool isExists = action.Exists(where);
if (action.RecordsAffected == -2)
{
result = false;
}
else
{
if (!isExists)
{
action.AllowInsertID = !row.PrimaryCell.IsNullOrEmpty;
action.Data.SetState(1, BreakOp.Null);
result = action.Insert(InsertOp.None);
}
else
{
action.Data.SetState(2);
result = action.Update(where);
}
}
if (!result)
{
string msg = "Error On : MDataTable.AcceptChanges.Auto." + mdt.TableName + " : [" + where + "] : " + action.DebugInfo;
sourceTable.DynamicData = msg;
Log.WriteLogToTxt(msg);
break;
}
#endregion
}
}
action.dalHelper.IsAllowRecordSql = true;//恢复SQL日志记录
if (_dalHelper == null)
{
action.EndTransation();
}
else
{
action.dalHelper = sourceHelper;//还原
}
}
return result;
}
internal bool Delete()
{
bool hasFK = (jointPrimaryIndex != null && jointPrimaryIndex.Count > 1) || mdt.Columns.JointPrimary.Count > 1;
if (hasFK)
{
return NormalDelete();
}
else
{
return BulkCopyDelete();//只有一个主键,没有外键关联,同时只有基础类型。
}
}
#region 批量插入
internal bool MsSqlBulkCopyInsert(bool keepID)
{
SqlTransaction sqlTran = null;
SqlConnection con = null;
bool isCreateDal = false;
try
{
CheckGUIDAndDateTime(DalType.MsSql);
string conn = AppConfig.GetConn(_Conn);
if (_dalHelper == null)
{
if (IsTruncate)
{
isCreateDal = true;
_dalHelper = DalCreate.CreateDal(conn);
}
else
{
con = new SqlConnection(conn);
con.Open();
}
}
bool isGoOn = true;
if (_dalHelper != null)
{
if (IsTruncate)
{
_dalHelper.isOpenTrans = true;
if (_dalHelper.ExeNonQuery(string.Format(SqlCreate.TruncateTable, SqlFormat.Keyword(mdt.TableName, dalTypeTo)), false) == -2)
{
isGoOn = false;
sourceTable.DynamicData = _dalHelper.debugInfo;
Log.WriteLogToTxt(_dalHelper.debugInfo.ToString());
}
}
if (isGoOn)
{
con = _dalHelper.Con as SqlConnection;
_dalHelper.OpenCon(null, AllowConnLevel.MasterBackup);//如果未开启,则开启,打开链接后,如果以前没执行过数据,事务对象为空,这时会产生事务对象
sqlTran = _dalHelper._tran as SqlTransaction;
}
}
if (isGoOn)
{
using (SqlBulkCopy sbc = new SqlBulkCopy(con, (keepID ? SqlBulkCopyOptions.KeepIdentity : SqlBulkCopyOptions.Default) | SqlBulkCopyOptions.FireTriggers, sqlTran))
{
sbc.BatchSize = 100000;
sbc.DestinationTableName = SqlFormat.Keyword(mdt.TableName, DalType.MsSql);
sbc.BulkCopyTimeout = AppConfig.DB.CommandTimeout;
foreach (MCellStruct column in mdt.Columns)
{
sbc.ColumnMappings.Add(column.ColumnName, column.ColumnName);
}
sbc.WriteToServer(mdt);
}
}
return true;
}
catch (Exception err)
{
sourceTable.DynamicData = err;
Log.WriteLogToTxt(err);
}
finally
{
if (_dalHelper == null)
{
con.Close();
con = null;
}
else if (isCreateDal)
{
_dalHelper.EndTransaction();
_dalHelper.Dispose();
}
}
return false;
}
internal bool OracleBulkCopyInsert()
{
CheckGUIDAndDateTime(DalType.Oracle);
string conn = DalCreate.FormatConn(DalType.Oracle, AppConfig.GetConn(_Conn));
Assembly ass = OracleDal.GetAssembly();
object sbc = ass.CreateInstance("Oracle.DataAccess.Client.OracleBulkCopy", false, BindingFlags.CreateInstance, null, new object[] { conn }, null, null);
Type sbcType = sbc.GetType();
try
{
sbcType.GetProperty("BatchSize").SetValue(sbc, 100000, null);
sbcType.GetProperty("BulkCopyTimeout").SetValue(sbc, AppConfig.DB.CommandTimeout, null);
sbcType.GetProperty("DestinationTableName").SetValue(sbc, SqlFormat.Keyword(mdt.TableName, DalType.Oracle), null);
PropertyInfo cInfo = sbcType.GetProperty("ColumnMappings");
object cObj = cInfo.GetValue(sbc, null);
MethodInfo addMethod = cInfo.PropertyType.GetMethods()[4];
foreach (MCellStruct column in mdt.Columns)
{
addMethod.Invoke(cObj, new object[] { column.ColumnName, column.ColumnName });
}
sbcType.GetMethods()[4].Invoke(sbc, new object[] { mdt });
return true;
}
catch (Exception err)
{
if (err.InnerException != null)
{
err = err.InnerException;
}
sourceTable.DynamicData = err;
Log.WriteLogToTxt(err);
return false;
}
finally
{
sbcType.GetMethod("Dispose").Invoke(sbc, null);
}
//using (Oracle.DataAccess.Client.OracleBulkCopy sbc = new OracleBulkCopy(conn, OracleBulkCopyOptions.Default))
//{
// sbc.BatchSize = 100000;
// sbc.DestinationTableName = mdt.TableName;
// foreach (MCellStruct column in mdt.Columns)
// {
// sbc.ColumnMappings.Add(column.ColumnName, column.ColumnName);
// }
// sbc.WriteToServer(mdt);
//}
//return true;
}
bool IsAllowBulkCopy(DalType dalType)
{
foreach (MCellStruct st in mdt.Columns)
{
switch (DataType.GetGroup(st.SqlType))
{
case 999:
return false;
}
}
try
{
if (dalType == DalType.Oracle && !HasSqlLoader())
{
return false;
}
string path = Path.GetTempPath() + "t.t";
if (!File.Exists(path))
{
File.Create(path).Close();//检测文件夹的读写权限
}
return IOHelper.Delete(path);
}
catch
{
}
return false;
}
internal bool LoadDataInsert(DalType dalType, bool keepID)
{
bool fillGUID = CheckGUIDAndDateTime(dalType);
bool isNeedCreateDal = (_dalHelper == null);
if (isNeedCreateDal && dalType != DalType.Oracle)
{
_dalHelper = DalCreate.CreateDal(_Conn);
_dalHelper.isAllowInterWriteLog = false;
}
string path = MDataTableToFile(mdt, fillGUID ? true : keepID, dalType);
string formatSql = dalType == DalType.MySql ? SqlCreate.MySqlBulkCopySql : SqlCreate.OracleBulkCopySql;
string sql = string.Format(formatSql, path, SqlFormat.Keyword(mdt.TableName, dalType),
AppConst.SplitChar, SqlCreate.GetColumnName(mdt.Columns, keepID, dalType));
if (dalType == DalType.Oracle)
{
string ctlPath = CreateCTL(sql, path);
sql = string.Format(SqlCreate.OracleSqlIDR, "sa/123456@ORCL", ctlPath);//只能用进程处理
}
try
{
if (dalType == DalType.Oracle)
{
return ExeSqlLoader(sql);
}
else
{
bool isGoOn = true;
if (IsTruncate)
{
_dalHelper.isOpenTrans = true;//开启事务
isGoOn = _dalHelper.ExeNonQuery(string.Format(SqlCreate.TruncateTable, SqlFormat.Keyword(mdt.TableName, dalTypeTo)), false) != -2;
}
if (isGoOn && _dalHelper.ExeNonQuery(sql, false) != -2)
{
return true;
}
}
}
catch (Exception err)
{
if (err.InnerException != null)
{
err = err.InnerException;
}
sourceTable.DynamicData = err;
Log.WriteLogToTxt(err);
}
finally
{
if (isNeedCreateDal && _dalHelper != null)
{
_dalHelper.EndTransaction();
_dalHelper.Dispose();
_dalHelper = null;
}
IOHelper.Delete(path);//删除文件。
}
return false;
}
private static string CreateCTL(string sql, string path)
{
path = path.Replace(".csv", ".ctl");
IOHelper.Write(path, sql);
return path;
}
private static string MDataTableToFile(MDataTable dt, bool keepID, DalType dalType)
{
string path = Path.GetTempPath() + dt.TableName + ".csv";
using (StreamWriter sw = new StreamWriter(path, false, new UTF8Encoding(false)))
{
MCellStruct ms;
string value;
foreach (MDataRow row in dt.Rows)
{
for (int i = 0; i < dt.Columns.Count; i++)
{
#region 设置值
ms = dt.Columns[i];
if (!keepID && ms.IsAutoIncrement)
{
continue;
}
else if (dalType == DalType.MySql && row[i].IsNull)
{
sw.Write("\\N");//Mysql用\N表示null值。
}
else
{
value = row[i].ToString();
if (ms.SqlType == SqlDbType.Bit)
{
int v = (value.ToLower() == "true" || value == "1") ? 1 : 0;
if (dalType == DalType.MySql)
{
byte[] b = new byte[1];
b[0] = (byte)v;
value = System.Text.Encoding.UTF8.GetString(b);//mysql必须用字节存档。
}
else
{
value = v.ToString();
}
}
else
{
value = value.Replace("\\", "\\\\");//处理转义符号
}
sw.Write(value);
}
if (i != dt.Columns.Count - 1)//不是最后一个就输出
{
sw.Write(AppConst.SplitChar);
}
#endregion
}
sw.Write('|');
sw.WriteLine();
sw.Write('|');
}
}
if (Path.DirectorySeparatorChar == '\\')
{
path = path.Replace(@"\", @"\\");
}
return path;
}
///
/// 检测GUID,若空,补值。
///
private bool CheckGUIDAndDateTime(DalType dal)
{
bool fillGUID = false;
int groupID;
for (int i = 0; i < mdt.Columns.Count; i++)
{
MCellStruct ms = mdt.Columns[i];
groupID = DataType.GetGroup(ms.SqlType);
if (groupID == 2)
{
for (int j = 0; j < mdt.Rows.Count; j++)
{
if (dal == DalType.MsSql && mdt.Rows[j][i].StringValue == DateTime.MinValue.ToString())
{
mdt.Rows[j][i].Value = SqlDateTime.MinValue;
}
else if (dal == DalType.Oracle && mdt.Rows[j][i].StringValue == SqlDateTime.MinValue.ToString())
{
mdt.Rows[j][i].Value = SqlDateTime.MinValue;
}
}
}
else if (ms.IsPrimaryKey && (groupID == 4 || (groupID == 0 && ms.MaxSize >= 36)))
{
string defaultValue = Convert.ToString(ms.DefaultValue);
bool isGuid = defaultValue == "" || defaultValue == "newid" || defaultValue == SqlValue.Guid;
if (isGuid && !fillGUID)
{
fillGUID = true;
}
for (int k = 0; k < mdt.Rows.Count; k++)
{
if (mdt.Rows[k][i].IsNullOrEmpty)
{
mdt.Rows[k][i].Value = isGuid ? Guid.NewGuid().ToString() : defaultValue;
}
}
}
}
return fillGUID;
}
#endregion
#region 批量更新
internal bool BulkCopyUpdate()
{
int count = 0, pageSize = 5000;
MDataTable dt = null;
bool result = false;
using (MAction action = new MAction(mdt.TableName, _Conn))
{
action.SetAopState(Aop.AopOp.CloseAll);
if (action.DalVersion.StartsWith("08"))
{
pageSize = 1000;
}
count = mdt.Rows.Count / pageSize + 1;
DbBase sourceHelper = action.dalHelper;
if (_dalHelper != null)
{
action.dalHelper = _dalHelper;
}
else
{
action.BeginTransation();
}
MCellStruct keyColumn = jointPrimaryIndex != null ? mdt.Columns[jointPrimaryIndex[0]] : mdt.Columns.FirstPrimary;
string columnName = keyColumn.ColumnName;
for (int i = 0; i < count; i++)
{
dt = mdt.Select(i + 1, pageSize, null);//分页读取
if (dt != null && dt.Rows.Count > 0)
{
#region 核心逻辑
string whereIn = SqlCreate.GetWhereIn(keyColumn, dt.GetColumnItems(columnName, BreakOp.NullOrEmpty, true), action.DalType);
MDataTable dtData = action.Select(whereIn);//获取远程数据。
dtData.Load(dt, keyColumn);//重新加载赋值。
action.IsIgnoreDeleteField = true;//处理如果存在IsDeleted,会被转Update(导致后续无法Insert)、外层也有判断,不会进来。
result = action.Delete(whereIn);
action.IsIgnoreDeleteField = false;
if (result)
{
dtData.DynamicData = action;
result = dtData.AcceptChanges(AcceptOp.InsertWithID);
}
if (!result)
{
if (_dalHelper == null)//有外部时由外部控制,没外部时直接回滚。
{
action.RollBack();//回滚被删除的代码。
}
break;
}
#endregion
}
}
if (_dalHelper == null)
{
action.EndTransation();
}
else
{
action.dalHelper = sourceHelper;//还原。
}
}
return result;
}
#endregion
#region 批量删除
internal bool BulkCopyDelete()
{
int count = 0, pageSize = 5000;
MDataTable dt = null;
bool result = false;
using (MAction action = new MAction(mdt.TableName, _Conn))
{
action.SetAopState(Aop.AopOp.CloseAll);
if (action.DalVersion.StartsWith("08"))
{
pageSize = 1000;
}
count = mdt.Rows.Count / pageSize + 1;
DbBase sourceHelper = action.dalHelper;
if (_dalHelper != null)
{
action.dalHelper = _dalHelper;
}
else
{
action.BeginTransation();
}
MCellStruct keyColumn = jointPrimaryIndex != null ? mdt.Columns[jointPrimaryIndex[0]] : mdt.Columns.FirstPrimary;
string columnName = keyColumn.ColumnName;
for (int i = 0; i < count; i++)
{
dt = mdt.Select(i + 1, pageSize, null);//分页读取
if (dt != null && dt.Rows.Count > 0)
{
#region 核心逻辑
string whereIn = SqlCreate.GetWhereIn(keyColumn, dt.GetColumnItems(columnName, BreakOp.NullOrEmpty, true), action.DalType);
result = action.Delete(whereIn) || action.RecordsAffected == 0;
if (result)
{
sourceTable.RecordsAffected += action.RecordsAffected;//记录总删除的数量。
}
else
{
sourceTable.RecordsAffected = 0;
string msg = "Error On : MDataTable.AcceptChanges.Delete." + mdt.TableName + " : where (" + whereIn + ") : " + action.DebugInfo;
sourceTable.DynamicData = msg;
Log.WriteLogToTxt(msg);
break;
}
#endregion
}
}
if (_dalHelper == null)
{
action.EndTransation();
}
else
{
action.dalHelper = sourceHelper;//还原。
}
}
return result;
}
#endregion
#region 注释掉
/*
internal bool SybaseBulkCopyInsert()
{
// string a, b, c;
string conn = DalCreate.FormatConn(DalType.Sybase, AppConfig.GetConn(_Conn));
using (Sybase.Data.AseClient.AseBulkCopy sbc = new Sybase.Data.AseClient.AseBulkCopy(conn, Sybase.Data.AseClient.AseBulkCopyOptions.KeepIdentity))
{
sbc.BatchSize = 100000;
sbc.DestinationTableName = mdt.TableName;
foreach (MCellStruct column in mdt.Columns)
{
Sybase.Data.AseClient.AseBulkCopyColumnMapping ac = new Sybase.Data.AseClient.AseBulkCopyColumnMapping();
ac.SourceColumn = ac.DestinationColumn = column.ColumnName;
sbc.ColumnMappings.Add(ac);
}
sbc.WriteToServer(mdt.ToDataTable());
}
return true;
//Assembly ass = SybaseDal.GetAssembly();
//object sbc = ass.CreateInstance("Sybase.Data.AseClient.AseBulkCopy", false, BindingFlags.CreateInstance, null, new object[] { conn }, null, null);
//Type sbcType = sbc.GetType();
//try
//{
// sbcType.GetProperty("BatchSize").SetValue(sbc, 100000, null);
// sbcType.GetProperty("DestinationTableName").SetValue(sbc, SqlFormat.Keyword(mdt.TableName, DalType.Sybase), null);
// PropertyInfo cInfo = sbcType.GetProperty("ColumnMappings");
// object cObj = cInfo.GetValue(sbc, null);
// MethodInfo addMethod = cInfo.PropertyType.GetMethods()[2];
// foreach (MCellStruct column in mdt.Columns)
// {
// object columnMapping = ass.CreateInstance("Sybase.Data.AseClient.AseBulkCopyColumnMapping", false, BindingFlags.CreateInstance, null, new object[] { column.ColumnName, column.ColumnName }, null, null);
// addMethod.Invoke(cObj, new object[] { columnMapping });
// }
// //Oracle.DataAccess.Client.OracleBulkCopy ttt = sbc as Oracle.DataAccess.Client.OracleBulkCopy;
// //ttt.WriteToServer(mdt);
// sbcType.GetMethods()[14].Invoke(sbc, new object[] { mdt.ToDataTable() });
// return true;
//}
//catch (Exception err)
//{
// Log.WriteLogToTxt(err);
// return false;
//}
//finally
//{
// sbcType.GetMethod("Dispose").Invoke(sbc, null);
//}
}
*/
#endregion
internal bool NomalInsert(bool keepID)
{
bool result = true;
using (MAction action = new MAction(mdt.TableName, _Conn))
{
DbBase sourceHelper = action.dalHelper;
action.SetAopState(Aop.AopOp.CloseAll);
if (_dalHelper != null)
{
action.dalHelper = _dalHelper;
}
else
{
action.BeginTransation();//事务由外部控制
}
action.dalHelper.IsAllowRecordSql = false;//屏蔽SQL日志记录
if (keepID)
{
action.SetIdentityInsertOn();
}
bool isGoOn = true;
if (IsTruncate)
{
if (dalTypeTo == DalType.Txt || dalTypeTo == DalType.Xml)
{
action.Delete("1=1");
}
else if (action.dalHelper.ExeNonQuery(string.Format(SqlCreate.TruncateTable, SqlFormat.Keyword(action.TableName, dalTypeTo)), false) == -2)
{
isGoOn = false;
sourceTable.DynamicData = action.DebugInfo;
Log.WriteLogToTxt(action.DebugInfo);
}
}
if (isGoOn)
{
MDataRow row;
for (int i = 0; i < mdt.Rows.Count; i++)
{
row = mdt.Rows[i];
action.ResetTable(row, false);
action.Data.SetState(1, BreakOp.Null);
result = action.Insert(InsertOp.None);
sourceTable.RecordsAffected = i;
if (!result)
{
string msg = "Error On : MDataTable.AcceptChanges.Insert." + mdt.TableName + " : [" + row.PrimaryCell.Value + "] : " + action.DebugInfo;
sourceTable.DynamicData = msg;
Log.WriteLogToTxt(msg);
break;
}
}
}
if (keepID)
{
action.SetIdentityInsertOff();
}
if (_dalHelper == null)
{
action.EndTransation();
}
action.dalHelper.IsAllowRecordSql = true;//恢复SQL日志记录
action.dalHelper = sourceHelper;//恢复原来,避免外来的链接被关闭。
}
return result;
}
internal bool NormalUpdate()
{
List indexList = new List();
bool result = true;
using (MAction action = new MAction(mdt.TableName, _Conn))
{
action.SetAopState(Aop.AopOp.CloseAll);
DbBase sourceHelper = action.dalHelper;
if (_dalHelper != null)
{
action.dalHelper = _dalHelper;
}
else
{
action.BeginTransation();
}
action.dalHelper.IsAllowRecordSql = false;//屏蔽SQL日志记录
MDataRow row;
for (int i = 0; i < mdt.Rows.Count; i++)
{
row = mdt.Rows[i];
if (row.GetState(true) > 1)
{
action.ResetTable(row, false);
string where = SqlCreate.GetWhere(action.DalType, GetJoinPrimaryCell(row));
result = action.Update(where) || action.RecordsAffected == 0;//没有可更新的数据,也返回true
if (action.RecordsAffected > 0)
{
sourceTable.RecordsAffected += action.RecordsAffected;//记录总更新的数量。
}
if (!result)
{
sourceTable.RecordsAffected = 0;
string msg = "Error On : MDataTable.AcceptChanges.Update." + mdt.TableName + " : where (" + where + ") : " + action.DebugInfo;
sourceTable.DynamicData = msg;
Log.WriteLogToTxt(msg);
break;
}
else
{
indexList.Add(i);
}
}
}
action.dalHelper.IsAllowRecordSql = true;//恢复SQL日志记录
if (_dalHelper == null)
{
action.EndTransation();
}
else
{
action.dalHelper = sourceHelper;//恢复原来,避免外来的链接被关闭。
}
}
if (result)
{
foreach (int index in indexList)
{
mdt.Rows[index].SetState(0);
}
indexList.Clear();
indexList = null;
}
return result;
}
internal bool NormalDelete()
{
bool result = true;
using (MAction action = new MAction(mdt.TableName, _Conn))
{
action.SetAopState(Aop.AopOp.CloseAll);
DbBase sourceHelper = action.dalHelper;
if (_dalHelper != null)
{
action.dalHelper = _dalHelper;
}
else
{
action.BeginTransation();
}
action.dalHelper.IsAllowRecordSql = false;//屏蔽SQL日志记录
MDataRow row;
for (int i = 0; i < mdt.Rows.Count; i++)
{
row = mdt.Rows[i];
action.ResetTable(row, false);
string where = SqlCreate.GetWhere(action.DalType, GetJoinPrimaryCell(row));
result = action.Delete(where) || action.RecordsAffected == 0;//没有可更新的数据,也返回true
if (action.RecordsAffected > 0)
{
sourceTable.RecordsAffected += action.RecordsAffected;//记录总删除的数量。
}
if (!result)
{
sourceTable.RecordsAffected = 0;
string msg = "Error On : MDataTable.AcceptChanges.Delete." + mdt.TableName + " : where (" + where + ") : " + action.DebugInfo;
sourceTable.DynamicData = msg;
Log.WriteLogToTxt(msg);
break;
}
}
action.dalHelper.IsAllowRecordSql = true;//恢复SQL日志记录
if (_dalHelper == null)
{
action.EndTransation();
}
else
{
action.dalHelper = sourceHelper;//恢复原来,避免外来的链接被关闭。
}
}
return result;
}
}
internal partial class MDataTableBatchAction
{
bool hasSqlLoader = false;
private bool HasSqlLoader()
{
hasSqlLoader = false;
Process proc = new Process();
proc.StartInfo.FileName = "sqlldr";
proc.StartInfo.CreateNoWindow = true;
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.OutputDataReceived += new DataReceivedEventHandler(proc_OutputDataReceived);
proc.Start();
proc.BeginOutputReadLine();
proc.WaitForExit();
return hasSqlLoader;
}
void proc_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
if (!hasSqlLoader)
{
hasSqlLoader = e.Data.StartsWith("SQL*Loader:");
}
}
//已经实现,但没有事务,所以暂时先不引入。
private bool ExeSqlLoader(string arg)
{
try
{
Process proc = new Process();
proc.StartInfo.FileName = "sqlldr";
proc.StartInfo.Arguments = arg;
proc.Start();
proc.WaitForExit();
return true;
}
catch
{
}
return false;
}
}
}