OracleFastBuilder.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. using Oracle.ManagedDataAccess.Client;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Data;
  5. using System.Linq;
  6. using System.Threading.Tasks;
  7. namespace SqlSugar
  8. {
  9. public class OracleFastBuilder : FastBuilder, IFastBuilder
  10. {
  11. public override DbFastestProperties DbFastestProperties { get; set; } = new DbFastestProperties()
  12. {
  13. IsMerge = true
  14. };
  15. private EntityInfo entityInfo;
  16. public OracleFastBuilder(EntityInfo entityInfo)
  17. {
  18. this.entityInfo = entityInfo;
  19. }
  20. public override string UpdateSql { get; set; } = "UPDATE (SELECT {4} FROM {2} TM,{3} TE WHERE {1})SET {0}";
  21. public override async Task CreateTempAsync<T>(DataTable dt)
  22. {
  23. var sqlBuilder = this.Context.Queryable<object>().SqlBuilder;
  24. var dts = dt.Columns.Cast<DataColumn>().Select(it => sqlBuilder.GetTranslationColumnName(it.ColumnName)).ToList();
  25. //await Task.FromResult(0);
  26. //throw new Exception("Oracle no support BulkUpdate");
  27. var oldTableName = dt.TableName;
  28. var columns = this.Context.EntityMaintenance.GetEntityInfo<T>().Columns.Where(it => it.IsPrimarykey).Select(it => it.DbColumnName).ToList();
  29. dt.TableName = "Temp" + SnowFlakeSingle.instance.getID().ToString();
  30. if (columns.Count() == 0&& DbFastestProperties!=null&& DbFastestProperties.WhereColumns.HasValue())
  31. {
  32. columns.AddRange(DbFastestProperties.WhereColumns);
  33. }
  34. var sql = this.Context.Queryable<T>().AS(oldTableName).Where(it => false).Select(string.Join(",", dts)).ToSql().Key;
  35. await this.Context.Ado.ExecuteCommandAsync($"create table {dt.TableName} as {sql} ");
  36. this.Context.DbMaintenance.AddPrimaryKeys(dt.TableName, columns.ToArray(), "Pk_" + SnowFlakeSingle.instance.getID().ToString());
  37. }
  38. public override async Task<int> UpdateByTempAsync(string tableName, string tempName, string[] updateColumns, string[] whereColumns)
  39. {
  40. var sqlBuilder = this.Context.Queryable<object>().SqlBuilder;
  41. Check.ArgumentNullException(!updateColumns.Any(), "update columns count is 0");
  42. Check.ArgumentNullException(!whereColumns.Any(), "where columns count is 0");
  43. var sets = string.Join(",", updateColumns.Select(it => $"TM{it}=TE{it}"));
  44. var wheres = string.Join(" AND ", whereColumns.Select(it => $"TM.{sqlBuilder.GetTranslationColumnName(it)}=TE.{sqlBuilder.GetTranslationColumnName(it)}"));
  45. var forms = string.Join(",", updateColumns.Select(it => $" TM.{sqlBuilder.GetTranslationColumnName(it)} TM{it},TE.{sqlBuilder.GetTranslationColumnName(it)} TE{it}")); ;
  46. string sql = string.Format(UpdateSql, sets, wheres, tableName, tempName, forms);
  47. return await this.Context.Ado.ExecuteCommandAsync(sql);
  48. }
  49. private OracleBulkCopy GetBulkCopyInstance()
  50. {
  51. if (this.Context.Ado.Connection.State == ConnectionState.Closed)
  52. {
  53. this.Context.Ado.Connection.Open();
  54. }
  55. OracleBulkCopy copy;
  56. if (this.Context.Ado.Transaction == null)
  57. {
  58. copy = new OracleBulkCopy((OracleConnection)this.Context.Ado.Connection, Oracle.ManagedDataAccess.Client.OracleBulkCopyOptions.Default);
  59. }
  60. else
  61. {
  62. copy = new OracleBulkCopy((OracleConnection)this.Context.Ado.Connection, OracleBulkCopyOptions.UseInternalTransaction);
  63. }
  64. copy.BulkCopyTimeout = this.Context.Ado.CommandTimeOut;
  65. return copy;
  66. }
  67. public override Task<int> Merge<T>(string tableName, DataTable dt, EntityInfo entityInfo, string[] whereColumns, string[] updateColumns,List<T> datas) where T : class
  68. {
  69. Check.Exception(this.entityInfo.Columns.Any(it => it.OracleSequenceName.HasValue()), "The BulkMerge method cannot be used for sequence", "BulkMerge方法不能用序列");
  70. var sqlBuilder = this.Context.Queryable<object>().SqlBuilder;
  71. var insertColumns = entityInfo.Columns
  72. .Where(it => it.IsIgnore == false)
  73. .Where(it => it.IsIdentity == false)
  74. .Where(it => it.InsertServerTime == false)
  75. .Where(it => it.InsertSql == null)
  76. .Where(it => it.OracleSequenceName == null)
  77. .Where(it => it.IsOnlyIgnoreInsert == false);
  78. var whereSql =string.Join(" AND ",whereColumns.Select(it=> $"tgt.{sqlBuilder.GetTranslationColumnName(it)}=src.{sqlBuilder.GetTranslationColumnName(it)}"));
  79. var updateColumnsSql = string.Join(" , ", updateColumns.Select(it => $"tgt.{sqlBuilder.GetTranslationColumnName(it)}=src.{sqlBuilder.GetTranslationColumnName(it)}"));
  80. var insertColumnsSqlTgt =string.Join(" , ", insertColumns.Select(it=>"tgt."+ sqlBuilder.GetTranslationColumnName(it.DbColumnName)));
  81. var insertColumnsSqlsrc = string.Join(" , ", insertColumns.Select(it => "src." + sqlBuilder.GetTranslationColumnName(it.DbColumnName)));
  82. var sql = $@"MERGE INTO {sqlBuilder.GetTranslationColumnName(tableName)} tgt
  83. USING {sqlBuilder.GetTranslationColumnName(dt.TableName)} src
  84. ON ({whereSql})
  85. WHEN MATCHED THEN
  86. UPDATE SET {updateColumnsSql}
  87. WHEN NOT MATCHED THEN
  88. INSERT ({insertColumnsSqlTgt})
  89. VALUES ({insertColumnsSqlsrc})";
  90. return this.Context.Ado.ExecuteCommandAsync(sql);
  91. }
  92. public Task<int> ExecuteBulkCopyAsync(DataTable dt)
  93. {
  94. var identityColumnInfo = this.entityInfo.Columns.FirstOrDefault(it => it.IsIdentity);
  95. if (identityColumnInfo != null)
  96. {
  97. throw new Exception("Oracle bulkcopy no support identity");
  98. }
  99. OracleBulkCopy copy = GetBulkCopyInstance();
  100. try
  101. {
  102. copy.DestinationTableName = dt.TableName;
  103. copy.WriteToServer(dt);
  104. }
  105. catch (Exception ex)
  106. {
  107. throw ex;
  108. }
  109. finally
  110. {
  111. CloseDb();
  112. }
  113. return Task.FromResult(dt.Rows.Count);
  114. }
  115. }
  116. }