From b72d4abfb8eab632ef31aa17ad10f5450e480a83 Mon Sep 17 00:00:00 2001 From: 28810 <28810@YEXIANGQIN> Date: Sat, 5 Jan 2019 18:28:01 +0800 Subject: [PATCH] =?UTF-8?q?oracle=20CodeFirst=20=E8=BF=9B=E8=A1=8C?= =?UTF-8?q?=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FreeSql.Tests/Oracle/OracleCodeFirstTest.cs | 220 ++++++++++++ FreeSql.Tests/g.cs | 5 + FreeSql/FreeSqlBuilder.cs | 4 +- FreeSql/Internal/Utils.cs | 20 +- FreeSql/MySql/MySqlCodeFirst.cs | 6 +- FreeSql/Oracle/Curd/OracleDelete.cs | 31 +- FreeSql/Oracle/Curd/OracleInsert.cs | 86 +++-- FreeSql/Oracle/Curd/OracleUpdate.cs | 31 +- .../Oracle/OracleAdo/OracleConnectionPool.cs | 5 + FreeSql/Oracle/OracleCodeFirst.cs | 340 +++++++++--------- FreeSql/Oracle/OracleUtils.cs | 8 +- FreeSql/PostgreSQL/PostgreSQLCodeFirst.cs | 12 +- FreeSql/SqlServer/SqlServerCodeFirst.cs | 4 +- 13 files changed, 501 insertions(+), 271 deletions(-) create mode 100644 FreeSql.Tests/Oracle/OracleCodeFirstTest.cs diff --git a/FreeSql.Tests/Oracle/OracleCodeFirstTest.cs b/FreeSql.Tests/Oracle/OracleCodeFirstTest.cs new file mode 100644 index 00000000..3402c069 --- /dev/null +++ b/FreeSql.Tests/Oracle/OracleCodeFirstTest.cs @@ -0,0 +1,220 @@ +using FreeSql.DataAnnotations; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Xunit; + +namespace FreeSql.Tests.Oracle { + public class OracleCodeFirstTest { + + [Fact] + public void AddField() { + var sql = g.oracle.CodeFirst.GetComparisonDDLStatements(); + + var id = g.oracle.Insert().AppendData(new TopicAddField { }).ExecuteIdentity(); + + //var inserted = g.oracle.Insert().AppendData(new TopicAddField { }).ExecuteInserted(); + } + + [Table(Name = "TopicAddField", OldName = "xxxtb.TopicAddField")] + public class TopicAddField { + [Column(IsIdentity = true)] + public int Id { get; set; } + + public string name { get; set; } + + [Column(DbType = "varchar2(200 char) not null", OldName = "title")] + public string title2 { get; set; } = "10"; + } + + [Fact] + public void GetComparisonDDLStatements() { + + var sql = g.oracle.CodeFirst.GetComparisonDDLStatements(); + if (string.IsNullOrEmpty(sql) == false) { + Assert.Equal(@"CREATE TABLE IF NOT EXISTS `cccddd`.`tb_alltype` ( + `Id` INT(11) NOT NULL AUTO_INCREMENT, + `testFieldBool` BIT(1) NOT NULL, + `testFieldSByte` TINYINT(3) NOT NULL, + `testFieldShort` SMALLINT(6) NOT NULL, + `testFieldInt` INT(11) NOT NULL, + `testFieldLong` BIGINT(20) NOT NULL, + `testFieldByte` TINYINT(3) UNSIGNED NOT NULL, + `testFieldUShort` SMALLINT(5) UNSIGNED NOT NULL, + `testFieldUInt` INT(10) UNSIGNED NOT NULL, + `testFieldULong` BIGINT(20) UNSIGNED NOT NULL, + `testFieldDouble` DOUBLE NOT NULL, + `testFieldFloat` FLOAT NOT NULL, + `testFieldDecimal` DECIMAL(10,2) NOT NULL, + `testFieldTimeSpan` TIME NOT NULL, + `testFieldDateTime` DATETIME NOT NULL, + `testFieldBytes` VARBINARY(255), + `testFieldString` VARCHAR(255), + `testFieldGuid` VARCHAR(36), + `testFieldBoolNullable` BIT(1), + `testFieldSByteNullable` TINYINT(3), + `testFieldShortNullable` SMALLINT(6), + `testFieldIntNullable` INT(11), + `testFielLongNullable` BIGINT(20), + `testFieldByteNullable` TINYINT(3) UNSIGNED, + `testFieldUShortNullable` SMALLINT(5) UNSIGNED, + `testFieldUIntNullable` INT(10) UNSIGNED, + `testFieldULongNullable` BIGINT(20) UNSIGNED, + `testFieldDoubleNullable` DOUBLE, + `testFieldFloatNullable` FLOAT, + `testFieldDecimalNullable` DECIMAL(10,2), + `testFieldTimeSpanNullable` TIME, + `testFieldDateTimeNullable` DATETIME, + `testFieldGuidNullable` VARCHAR(36), + `testFieldPoint` POINT, + `testFieldLineString` LINESTRING, + `testFieldPolygon` POLYGON, + `testFieldMultiPoint` MULTIPOINT, + `testFieldMultiLineString` MULTILINESTRING, + `testFieldMultiPolygon` MULTIPOLYGON, + `testFieldEnum1` ENUM('E1','E2','E3') NOT NULL, + `testFieldEnum1Nullable` ENUM('E1','E2','E3'), + `testFieldEnum2` SET('F1','F2','F3') NOT NULL, + `testFieldEnum2Nullable` SET('F1','F2','F3'), + PRIMARY KEY (`Id`) +) Engine=InnoDB CHARACTER SET utf8; +", sql); + } + + //sql = g.oracle.CodeFirst.GetComparisonDDLStatements(); + } + + IInsert insert => g.oracle.Insert(); + ISelect select => g.oracle.Select(); + + [Fact] + public void CurdAllField() { + var item = new TableAllType { }; + item.Id = (int)insert.AppendData(item).ExecuteIdentity(); + + var newitem = select.Where(a => a.Id == item.Id).ToOne(); + + var item2 = new TableAllType { + testFieldBool = true, + testFieldBoolNullable = true, + testFieldByte = 255, + testFieldByteNullable = 127, + testFieldBytes = Encoding.UTF8.GetBytes("我是中国人"), + testFieldDateTime = DateTime.Now, + testFieldDateTimeNullable = DateTime.Now.AddHours(-1), + testFieldDecimal = 99.99M, + testFieldDecimalNullable = 99.98M, + testFieldDouble = 999.99, + testFieldDoubleNullable = 999.98, + testFieldEnum1 = TableAllTypeEnumType1.e5, + testFieldEnum1Nullable = TableAllTypeEnumType1.e3, + testFieldEnum2 = TableAllTypeEnumType2.f2, + testFieldEnum2Nullable = TableAllTypeEnumType2.f3, + testFieldFloat = 19.99F, + testFieldFloatNullable = 19.98F, + testFieldGuid = Guid.NewGuid(), + testFieldGuidNullable = Guid.NewGuid(), + testFieldInt = int.MaxValue, + testFieldIntNullable = int.MinValue, + testFieldLineString = new MygisLineString(new[] { new MygisCoordinate2D(10, 10), new MygisCoordinate2D(50, 10) }), + testFieldLong = long.MaxValue, + testFieldMultiLineString = new MygisMultiLineString(new[] { + new[] { new MygisCoordinate2D(10, 10), new MygisCoordinate2D(50, 10) }, + new[] { new MygisCoordinate2D(50, 10), new MygisCoordinate2D(10, 100) } }), + testFieldMultiPoint = new MygisMultiPoint(new[] { new MygisCoordinate2D(11, 11), new MygisCoordinate2D(51, 11) }), + testFieldMultiPolygon = new MygisMultiPolygon(new[] { + new MygisPolygon(new[] { + new[] { new MygisCoordinate2D(10, 10), new MygisCoordinate2D(50, 10), new MygisCoordinate2D(10, 50), new MygisCoordinate2D(10, 10) }, + new[] { new MygisCoordinate2D(10, 10), new MygisCoordinate2D(50, 10), new MygisCoordinate2D(10, 50), new MygisCoordinate2D(10, 10) }, + new[] { new MygisCoordinate2D(10, 10), new MygisCoordinate2D(50, 10), new MygisCoordinate2D(10, 50), new MygisCoordinate2D(10, 10) }, + new[] { new MygisCoordinate2D(10, 10), new MygisCoordinate2D(50, 10), new MygisCoordinate2D(10, 50), new MygisCoordinate2D(10, 10) } }), + new MygisPolygon(new[] { + new[] { new MygisCoordinate2D(10, 10), new MygisCoordinate2D(50, 10), new MygisCoordinate2D(10, 50), new MygisCoordinate2D(10, 10) }, + new[] { new MygisCoordinate2D(10, 10), new MygisCoordinate2D(50, 10), new MygisCoordinate2D(10, 50), new MygisCoordinate2D(10, 10) }, + new[] { new MygisCoordinate2D(10, 10), new MygisCoordinate2D(50, 10), new MygisCoordinate2D(10, 50), new MygisCoordinate2D(10, 10) }, + new[] { new MygisCoordinate2D(10, 10), new MygisCoordinate2D(50, 10), new MygisCoordinate2D(10, 50), new MygisCoordinate2D(10, 10) } }) }), + testFieldPoint = new MygisPoint(99, 99), + testFieldPolygon = new MygisPolygon(new[] { + new[] { new MygisCoordinate2D(10, 10), new MygisCoordinate2D(50, 10), new MygisCoordinate2D(10, 50), new MygisCoordinate2D(10, 10) }, + new[] { new MygisCoordinate2D(10, 10), new MygisCoordinate2D(50, 10), new MygisCoordinate2D(10, 50), new MygisCoordinate2D(10, 10) }, + new[] { new MygisCoordinate2D(10, 10), new MygisCoordinate2D(50, 10), new MygisCoordinate2D(10, 50), new MygisCoordinate2D(10, 10) }, + new[] { new MygisCoordinate2D(10, 10), new MygisCoordinate2D(50, 10), new MygisCoordinate2D(10, 50), new MygisCoordinate2D(10, 10) } }), + testFieldSByte = 100, + testFieldSByteNullable = 99, + testFieldShort = short.MaxValue, + testFieldShortNullable = short.MinValue, + testFieldString = "我是中国人string", + testFieldTimeSpan = TimeSpan.FromSeconds(999), + testFieldTimeSpanNullable = TimeSpan.FromSeconds(60), + testFieldUInt = uint.MaxValue, + testFieldUIntNullable = uint.MinValue, + testFieldULong = ulong.MaxValue, + testFieldULongNullable = ulong.MinValue, + testFieldUShort = ushort.MaxValue, + testFieldUShortNullable = ushort.MinValue, + testFielLongNullable = long.MinValue + }; + item2.Id = (int)insert.AppendData(item2).ExecuteIdentity(); + var newitem2 = select.Where(a => a.Id == item2.Id).ToOne(); + + var items = select.ToList(); + } + + [Table(Name = "tb_alltype")] + class TableAllType { + [Column(IsIdentity = true, IsPrimary = true)] + public int Id { get; set; } + + public bool testFieldBool { get; set; } + public sbyte testFieldSByte { get; set; } + public short testFieldShort { get; set; } + public int testFieldInt { get; set; } + public long testFieldLong { get; set; } + public byte testFieldByte { get; set; } + public ushort testFieldUShort { get; set; } + public uint testFieldUInt { get; set; } + public ulong testFieldULong { get; set; } + public double testFieldDouble { get; set; } + public float testFieldFloat { get; set; } + public decimal testFieldDecimal { get; set; } + public TimeSpan testFieldTimeSpan { get; set; } + public DateTime testFieldDateTime { get; set; } + public byte[] testFieldBytes { get; set; } + public string testFieldString { get; set; } + public Guid testFieldGuid { get; set; } + + public bool? testFieldBoolNullable { get; set; } + public sbyte? testFieldSByteNullable { get; set; } + public short? testFieldShortNullable { get; set; } + public int? testFieldIntNullable { get; set; } + public long? testFielLongNullable { get; set; } + public byte? testFieldByteNullable { get; set; } + public ushort? testFieldUShortNullable { get; set; } + public uint? testFieldUIntNullable { get; set; } + public ulong? testFieldULongNullable { get; set; } + public double? testFieldDoubleNullable { get; set; } + public float? testFieldFloatNullable { get; set; } + public decimal? testFieldDecimalNullable { get; set; } + public TimeSpan? testFieldTimeSpanNullable { get; set; } + public DateTime? testFieldDateTimeNullable { get; set; } + public Guid? testFieldGuidNullable { get; set; } + + public MygisPoint testFieldPoint { get; set; } + public MygisLineString testFieldLineString { get; set; } + public MygisPolygon testFieldPolygon { get; set; } + public MygisMultiPoint testFieldMultiPoint { get; set; } + public MygisMultiLineString testFieldMultiLineString { get; set; } + public MygisMultiPolygon testFieldMultiPolygon { get; set; } + + public TableAllTypeEnumType1 testFieldEnum1 { get; set; } + public TableAllTypeEnumType1? testFieldEnum1Nullable { get; set; } + public TableAllTypeEnumType2 testFieldEnum2 { get; set; } + public TableAllTypeEnumType2? testFieldEnum2Nullable { get; set; } + } + + public enum TableAllTypeEnumType1 { e1, e2, e3, e5 } + [Flags] public enum TableAllTypeEnumType2 { f1, f2, f3 } + } +} diff --git a/FreeSql.Tests/g.cs b/FreeSql.Tests/g.cs index d0ec4ff1..3a570938 100644 --- a/FreeSql.Tests/g.cs +++ b/FreeSql.Tests/g.cs @@ -28,4 +28,9 @@ public class g { .UseAutoSyncStructure(true) .UseSyncStructureToLower(true) .Build(); + + public static IFreeSql oracle = new FreeSql.FreeSqlBuilder() + .UseConnectionString(FreeSql.DataType.Oracle, "user id=user1;password=123456;data source=//127.0.0.1:1521/XE;Pooling=true;Max Pool Size=10") + .UseAutoSyncStructure(true) + .Build(); } diff --git a/FreeSql/FreeSqlBuilder.cs b/FreeSql/FreeSqlBuilder.cs index d9cde2e6..4c530c32 100644 --- a/FreeSql/FreeSqlBuilder.cs +++ b/FreeSql/FreeSqlBuilder.cs @@ -92,7 +92,7 @@ namespace FreeSql { case DataType.MySql: ret = new MySql.MySqlProvider(_cache, _logger, _masterConnectionString, _slaveConnectionString); break; case DataType.SqlServer: ret = new SqlServer.SqlServerProvider(_cache, _logger, _masterConnectionString, _slaveConnectionString); break; case DataType.PostgreSQL: ret = new PostgreSQL.PostgreSQLProvider(_cache, _logger, _masterConnectionString, _slaveConnectionString); break; - //case DataType.Oracle: ret = new Oracle.OracleProvider(_cache, _logger, _masterConnectionString, _slaveConnectionString); break; + case DataType.Oracle: ret = new Oracle.OracleProvider(_cache, _logger, _masterConnectionString, _slaveConnectionString); break; } if (ret != null) { ret.CodeFirst.IsAutoSyncStructure = _isAutoSyncStructure; @@ -105,5 +105,5 @@ namespace FreeSql { } } - public enum DataType { MySql, SqlServer, PostgreSQL, /*Oracle*/ } + public enum DataType { MySql, SqlServer, PostgreSQL, Oracle } } diff --git a/FreeSql/Internal/Utils.cs b/FreeSql/Internal/Utils.cs index 0ac5acb0..2e918493 100644 --- a/FreeSql/Internal/Utils.cs +++ b/FreeSql/Internal/Utils.cs @@ -56,10 +56,18 @@ namespace FreeSql.Internal { if (colattr.DbType?.Contains("NOT NULL") == true) colattr.IsNullable = false; if (string.IsNullOrEmpty(colattr.Name)) colattr.Name = p.Name; if (common.CodeFirst.IsSyncStructureToLower) colattr.Name = colattr.Name.ToLower(); - - if ((colattr.IsNullable == false || colattr.IsIdentity || colattr.IsPrimary) && colattr.DbType.Contains("NOT NULL") == false) colattr.DbType += " NOT NULL"; + + if ((colattr.IsNullable == false || colattr.IsIdentity || colattr.IsPrimary) && colattr.DbType.Contains("NOT NULL") == false) { + colattr.IsNullable = false; + colattr.DbType += " NOT NULL"; + } if (colattr.IsNullable == true && colattr.DbType.Contains("NOT NULL")) colattr.DbType = colattr.DbType.Replace("NOT NULL", ""); - colattr.DbType = Regex.Replace(colattr.DbType, @"\([^\)]+\)", m => Regex.Replace(m.Groups[0].Value, @"\s", "")); + colattr.DbType = Regex.Replace(colattr.DbType, @"\([^\)]+\)", m => { + var tmpLt = Regex.Replace(m.Groups[0].Value, @"\s", ""); + if (tmpLt.Contains("CHAR")) tmpLt = tmpLt.Replace("CHAR", " CHAR"); + if (tmpLt.Contains("BYTE")) tmpLt = tmpLt.Replace("BYTE", " BYTE"); + return tmpLt; + }); colattr.DbDefautValue = trytb.Properties[p.Name].GetValue(Activator.CreateInstance(trytb.Type)); if (colattr.DbDefautValue == null) colattr.DbDefautValue = tp?.defaultValue; if (colattr.IsNullable == false && colattr.DbDefautValue == null) { @@ -77,7 +85,11 @@ namespace FreeSql.Internal { trytb.ColumnsByCs.Add(p.Name, col); } trytb.Primarys = trytb.Columns.Values.Where(a => a.Attribute.IsPrimary).ToArray(); - if (trytb.Primarys.Any() == false) trytb.Primarys = trytb.Columns.Values.Where(a => a.Attribute.IsIdentity).ToArray(); + if (trytb.Primarys.Any() == false) { + trytb.Primarys = trytb.Columns.Values.Where(a => a.Attribute.IsIdentity).ToArray(); + foreach(var col in trytb.Primarys) + col.Attribute.IsPrimary = true; + } _cacheGetTableByEntity.TryAdd(entity.FullName, trytb); return trytb; } diff --git a/FreeSql/MySql/MySqlCodeFirst.cs b/FreeSql/MySql/MySqlCodeFirst.cs index 6fe268db..67efa3e8 100644 --- a/FreeSql/MySql/MySqlCodeFirst.cs +++ b/FreeSql/MySql/MySqlCodeFirst.cs @@ -49,7 +49,7 @@ namespace FreeSql.MySql { { typeof(byte[]).FullName, (MySqlDbType.VarBinary, "varbinary", "varbinary(255)", false, null, new byte[0]) }, { typeof(string).FullName, (MySqlDbType.VarChar, "varchar", "varchar(255)", false, null, "") }, - { typeof(Guid).FullName, (MySqlDbType.VarChar, "char", "char(36)", false, false, Guid.Empty) },{ typeof(Guid?).FullName, (MySqlDbType.VarChar, "char", "char(36)", false, true, null) }, + { typeof(Guid).FullName, (MySqlDbType.VarChar, "char", "char(36) NOT NULL", false, false, Guid.Empty) },{ typeof(Guid?).FullName, (MySqlDbType.VarChar, "char", "char(36)", false, true, null) }, { typeof(MygisPoint).FullName, (MySqlDbType.Geometry, "point", "point", false, null, new MygisPoint(0, 0)) }, { typeof(MygisLineString).FullName, (MySqlDbType.Geometry, "linestring", "linestring", false, null, new MygisLineString(new[]{new MygisCoordinate2D(),new MygisCoordinate2D()})) }, @@ -229,9 +229,9 @@ where a.table_schema in ({0}) and a.table_name in ({1})".FormatMySql(tboldname ? //insertvalue = $"cast({insertvalue} as {tbcol.Attribute.DbType.Split(' ').First()})"; } if (tbcol.Attribute.IsNullable != tbstructcol.is_nullable) - insertvalue = $"ifnull({insertvalue},{_commonUtils.FormatSql("{0}", tbcol.Attribute.DbDefautValue).Replace("'", "''")})"; + insertvalue = $"ifnull({insertvalue},{_commonUtils.FormatSql("{0}", tbcol.Attribute.DbDefautValue)})"; } else if (tbcol.Attribute.IsNullable == false) - insertvalue = _commonUtils.FormatSql("{0}", tbcol.Attribute.DbDefautValue).Replace("'", "''"); + insertvalue = _commonUtils.FormatSql("{0}", tbcol.Attribute.DbDefautValue); sb.Append(insertvalue).Append(", "); } sb.Remove(sb.Length - 2, 2).Append(" FROM ").Append(tablename).Append(";\r\n"); diff --git a/FreeSql/Oracle/Curd/OracleDelete.cs b/FreeSql/Oracle/Curd/OracleDelete.cs index 90b0b61a..7525b00e 100644 --- a/FreeSql/Oracle/Curd/OracleDelete.cs +++ b/FreeSql/Oracle/Curd/OracleDelete.cs @@ -1,4 +1,5 @@ 锘縰sing FreeSql.Internal; +using System; using System.Collections.Generic; using System.Data; using System.Text; @@ -12,34 +13,10 @@ namespace FreeSql.Oracle.Curd { } public override List ExecuteDeleted() { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.QuoteReadColumn(col.CsType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - return _orm.Ado.Query(CommandType.Text, sb.ToString(), _params.ToArray()); + throw new NotImplementedException(); } - async public override Task> ExecuteDeletedAsync() { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.QuoteReadColumn(col.CsType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - return await _orm.Ado.QueryAsync(CommandType.Text, sb.ToString(), _params.ToArray()); + public override Task> ExecuteDeletedAsync() { + throw new NotImplementedException(); } } } diff --git a/FreeSql/Oracle/Curd/OracleInsert.cs b/FreeSql/Oracle/Curd/OracleInsert.cs index af8ac146..840b8c73 100644 --- a/FreeSql/Oracle/Curd/OracleInsert.cs +++ b/FreeSql/Oracle/Curd/OracleInsert.cs @@ -1,4 +1,7 @@ 锘縰sing FreeSql.Internal; +using FreeSql.Internal.Model; +using Oracle.ManagedDataAccess.Client; +using System; using System.Collections.Generic; using System.Data; using System.Data.Common; @@ -18,29 +21,35 @@ namespace FreeSql.Oracle.Curd { var sb = new StringBuilder(); sb.Append("INSERT INTO ").Append(_commonUtils.QuoteSqlName(_table.DbName)).Append("("); var colidx = 0; + var colidxAndIdent = 0; foreach (var col in _table.Columns.Values) if (_ignore.ContainsKey(col.Attribute.Name) == false) { - if (colidx > 0) sb.Append(", "); + if (colidxAndIdent > 0) sb.Append(", "); sb.Append(_commonUtils.QuoteSqlName(col.Attribute.Name)); - ++colidx; + if (col.Attribute.IsIdentity == false) ++colidx; + ++colidxAndIdent; } sb.Append(") VALUES"); + _identCol = null; _params = new DbParameter[colidx * _source.Count]; var didx = 0; foreach (var d in _source) { if (didx > 0) sb.Append(", "); sb.Append("("); var colidx2 = 0; + var colidx2AndIdent = 0; foreach (var col in _table.Columns.Values) if (_ignore.ContainsKey(col.Attribute.Name) == false) { - if (colidx2 > 0) sb.Append(", "); + if (colidx2AndIdent > 0) sb.Append(", "); if (col.Attribute.IsIdentity) { sb.Append(_commonUtils.QuoteSqlName($"{Utils.GetCsName(_table.DbName)}_seq_{col.Attribute.Name}")).Append(".nextval"); + _identCol = col; } else { sb.Append(_commonUtils.QuoteWriteParamter(col.CsType, $"{_commonUtils.QuoteParamterName(col.CsName)}{didx}")); _params[didx * colidx + colidx2] = _commonUtils.AppendParamter(null, $"{col.CsName}{didx}", col.CsType, _table.Properties.TryGetValue(col.CsName, out var tryp) ? tryp.GetValue(d) : null); + ++colidx2; } - ++colidx2; + ++colidx2AndIdent; } sb.Append(")"); ++didx; @@ -48,58 +57,83 @@ namespace FreeSql.Oracle.Curd { return sb.ToString(); } + ColumnInfo _identCol; public override long ExecuteIdentity() { var sql = this.ToSql(); if (string.IsNullOrEmpty(sql)) return 0; - var identCols = _table.Columns.Where(a => a.Value.Attribute.IsIdentity); - if (identCols.Any() == false) { + if (_identCol == null) { _orm.Ado.ExecuteNonQuery(CommandType.Text, sql, _params); return 0; } - return long.TryParse(string.Concat(_orm.Ado.ExecuteScalar(CommandType.Text, string.Concat(sql, " RETURNING ", _commonUtils.QuoteSqlName(identCols.First().Value.Attribute.Name)), _params)), out var trylng) ? trylng : 0; + var identColName = _commonUtils.QuoteSqlName(_identCol.Attribute.Name); + var identParam = _commonUtils.AppendParamter(null, $"{_identCol.CsName}99", _identCol.CsType, 0) as OracleParameter; + identParam.Direction = ParameterDirection.Output; + _orm.Ado.ExecuteNonQuery(CommandType.Text, $"{sql} RETURNING {identColName} INTO {identParam.ParameterName}", _params.Concat(new[] { identParam }).ToArray()); + return long.TryParse(string.Concat(identParam.Value), out var trylng) ? trylng : 0; } async public override Task ExecuteIdentityAsync() { var sql = this.ToSql(); if (string.IsNullOrEmpty(sql)) return 0; - var identCols = _table.Columns.Where(a => a.Value.Attribute.IsIdentity); - if (identCols.Any() == false) { + if (_identCol == null) { await _orm.Ado.ExecuteNonQueryAsync(CommandType.Text, sql, _params); return 0; } - return long.TryParse(string.Concat(await _orm.Ado.ExecuteScalarAsync(CommandType.Text, string.Concat(sql, " RETURNING ", _commonUtils.QuoteSqlName(identCols.First().Value.Attribute.Name)), _params)), out var trylng) ? trylng : 0; + var identColName = _commonUtils.QuoteSqlName(_identCol.Attribute.Name); + var identParam = _commonUtils.AppendParamter(null, $"{_identCol.CsName}99", _identCol.CsType, 0) as OracleParameter; + identParam.Direction = ParameterDirection.Output; + await _orm.Ado.ExecuteNonQueryAsync(CommandType.Text, $"{sql} RETURNING {identColName} INTO {identParam.ParameterName}", _params.Concat(new[] { identParam }).ToArray()); + return long.TryParse(string.Concat(identParam.Value), out var trylng) ? trylng : 0; } public override List ExecuteInserted() { + throw new NotImplementedException(); + var sql = this.ToSql(); if (string.IsNullOrEmpty(sql)) return new List(); var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); + sb.Append(@"declare +type v_tp_rec is record("); var colidx = 0; foreach (var col in _table.Columns.Values) { if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.QuoteReadColumn(col.CsType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + sb.Append(_commonUtils.QuoteSqlName(col.CsName)).Append(" ").Append(_commonUtils.QuoteSqlName(_table.DbName)).Append(".").Append(_commonUtils.QuoteSqlName(col.Attribute.Name)).Append("%type"); ++colidx; } + sb.Append(@"); +type v_tp_tab is table of v_tp_rec; +v_tab v_tp_tab; +begin +"); + + sb.Append(sql).Append(" RETURNING "); + colidx = 0; + foreach (var col in _table.Columns.Values) { + if (colidx > 0) sb.Append(", "); + sb.Append(_commonUtils.QuoteReadColumn(col.CsType, _commonUtils.QuoteSqlName(col.Attribute.Name))); + ++colidx; + } + sb.Append(@"bulk collect into v_tab; +for i in 1..v_tab.count loop + dbms_output.put_line("); + //v_tab(i).empno||'-'||v_tab(i).ename + colidx = 0; + foreach (var col in _table.Columns.Values) { + if (colidx > 0) sb.Append("||'-'||"); + sb.Append("v_tab(i).").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + sb.Append(@"); +end loop; +end; +"); return _orm.Ado.Query(CommandType.Text, sb.ToString(), _params); } - async public override Task> ExecuteInsertedAsync() { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.QuoteReadColumn(col.CsType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - return await _orm.Ado.QueryAsync(CommandType.Text, sb.ToString(), _params); + public override Task> ExecuteInsertedAsync() { + throw new NotImplementedException(); } } } diff --git a/FreeSql/Oracle/Curd/OracleUpdate.cs b/FreeSql/Oracle/Curd/OracleUpdate.cs index 8e7d6d3d..a7ad6a6a 100644 --- a/FreeSql/Oracle/Curd/OracleUpdate.cs +++ b/FreeSql/Oracle/Curd/OracleUpdate.cs @@ -1,5 +1,6 @@ 锘縰sing FreeSql.Internal; using FreeSql.Internal.Model; +using System; using System.Collections.Generic; using System.Data; using System.Linq; @@ -15,34 +16,10 @@ namespace FreeSql.Oracle.Curd { } public override List ExecuteUpdated() { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.QuoteReadColumn(col.CsType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - return _orm.Ado.Query(CommandType.Text, sb.ToString(), _params.Concat(_paramsSource).ToArray()); + throw new NotImplementedException(); } - async public override Task> ExecuteUpdatedAsync() { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.QuoteReadColumn(col.CsType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - return await _orm.Ado.QueryAsync(CommandType.Text, sb.ToString(), _params.Concat(_paramsSource).ToArray()); + public override Task> ExecuteUpdatedAsync() { + throw new NotImplementedException(); } protected override void ToSqlCase(StringBuilder caseWhen, ColumnInfo[] primarys) { diff --git a/FreeSql/Oracle/OracleAdo/OracleConnectionPool.cs b/FreeSql/Oracle/OracleAdo/OracleConnectionPool.cs index 6d973d22..dcddb47c 100644 --- a/FreeSql/Oracle/OracleAdo/OracleConnectionPool.cs +++ b/FreeSql/Oracle/OracleAdo/OracleConnectionPool.cs @@ -14,8 +14,13 @@ namespace FreeSql.Oracle { internal Action availableHandler; internal Action unavailableHandler; + internal string UserId { get; set; } public OracleConnectionPool(string name, string connectionString, Action availableHandler, Action unavailableHandler) : base(null) { + var userIdMatch = Regex.Match(connectionString, @"User\s+Id\s*=\s*([^;]+)", RegexOptions.IgnoreCase); + if (userIdMatch.Success == false) throw new Exception(@"浠 ConnectionString 涓棤娉曞尮閰 User\s+Id\s+=([^;]+)"); + this.UserId = userIdMatch.Groups[1].Value.Trim().ToUpper(); + var policy = new OracleConnectionPoolPolicy { _pool = this, Name = name diff --git a/FreeSql/Oracle/OracleCodeFirst.cs b/FreeSql/Oracle/OracleCodeFirst.cs index 97c5bda4..c7c9ebe1 100644 --- a/FreeSql/Oracle/OracleCodeFirst.cs +++ b/FreeSql/Oracle/OracleCodeFirst.cs @@ -45,12 +45,12 @@ namespace FreeSql.Oracle { { typeof(TimeSpan).FullName, (OracleDbType.IntervalDS, "interval day to second","interval day(2) to second(6) NOT NULL", false, false, 0) },{ typeof(TimeSpan?).FullName, (OracleDbType.IntervalDS, "interval day to second", "interval day(2) to second(6) NULL",false, true, null) }, { typeof(DateTime).FullName, (OracleDbType.TimeStamp, "timestamp", "timestamp(6) NOT NULL", false, false, new DateTime(1970,1,1)) },{ typeof(DateTime?).FullName, (OracleDbType.TimeStamp, "timestamp", "timestamp(6) NULL", false, true, null) }, - { typeof(DateTimeOffset).FullName, (OracleDbType.TimeStampLTZ, "timestamp with local time zone", "timestamp(6) with local time zone NOT NULL", false, false, new DateTime(1970,1,1)) },{ typeof(DateTime?).FullName, (OracleDbType.TimeStamp, "timestamp with local time zone", "timestamp(6) with local time zone NULL", false, true, null) }, + { typeof(DateTimeOffset).FullName, (OracleDbType.TimeStampLTZ, "timestamp with local time zone", "timestamp(6) with local time zone NOT NULL", false, false, new DateTime(1970,1,1)) },{ typeof(DateTimeOffset?).FullName, (OracleDbType.TimeStampLTZ, "timestamp with local time zone", "timestamp(6) with local time zone NULL", false, true, null) }, { typeof(byte[]).FullName, (OracleDbType.Blob, "blog", "blog(4000) NULL", false, null, new byte[0]) }, { typeof(string).FullName, (OracleDbType.NVarchar2, "nvarchar2", "nvarchar2(255) NULL", false, null, "") }, - { typeof(Guid).FullName, (OracleDbType.Char, "char", "char(36 BYTE)", false, false, Guid.Empty) },{ typeof(Guid?).FullName, (OracleDbType.Char, "char", "char(36 BYTE) NULL", false, true, null) }, + { typeof(Guid).FullName, (OracleDbType.Char, "char", "char(36 BYTE) NOT NULL", false, false, Guid.Empty) },{ typeof(Guid?).FullName, (OracleDbType.Char, "char", "char(36 BYTE) NULL", false, true, null) }, }; public (int type, string dbtype, string dbtypeFull, bool? isnullable, object defaultValue)? GetDbInfo(Type type) { @@ -75,77 +75,60 @@ namespace FreeSql.Oracle { public string GetComparisonDDLStatements() => this.GetComparisonDDLStatements(typeof(TEntity)); public string GetComparisonDDLStatements(params Type[] entityTypes) { - var conn = _orm.Ado.MasterPool.Get(TimeSpan.FromSeconds(5)); + var userId = (_orm.Ado.MasterPool as OracleConnectionPool).UserId; var seqcols = new List<(ColumnInfo, string[], bool)>(); //搴忓垪 - var database = conn.Value.Database; - Func ExecuteScalar = (db, sql) => { - if (string.Compare(database, db) != 0) conn.Value.ChangeDatabase(db); - try { - using (var cmd = conn.Value.CreateCommand()) { - cmd.CommandText = sql; - cmd.CommandType = CommandType.Text; - return cmd.ExecuteScalar(); - } - } finally { - if (string.Compare(database, db) != 0) conn.Value.ChangeDatabase(database); - } - }; var sb = new StringBuilder(); - try { - foreach (var entityType in entityTypes) { - if (sb.Length > 0) sb.Append("\r\n"); - var tb = _commonUtils.GetTableByEntity(entityType); - var tbname = tb.DbName.Split(new[] { '.' }, 2); - if (tbname?.Length == 1) tbname = new[] { database, tbname[0] }; + var sbDeclare = new StringBuilder(); + foreach (var entityType in entityTypes) { + if (sb.Length > 0) sb.Append("\r\n"); + var tb = _commonUtils.GetTableByEntity(entityType); + var tbname = tb.DbName.Split(new[] { '.' }, 2); + if (tbname?.Length == 1) tbname = new[] { userId, tbname[0] }; - var tboldname = tb.DbOldName?.Split(new[] { '.' }, 2); //鏃ц〃鍚 - if (tboldname?.Length == 1) tboldname = new[] { database, tboldname[0] }; + var tboldname = tb.DbOldName?.Split(new[] { '.' }, 2); //鏃ц〃鍚 + if (tboldname?.Length == 1) tboldname = new[] { userId, tboldname[0] }; - if (string.Compare(tbname[0], database, true) != 0 && ExecuteScalar(database, " select 1 from sys.dba_users where username={0}".FormatOracleSQL(tbname[0])) == null) //鍒涘缓鏁版嵁搴 - throw new NotImplementedException($"Oracle CodeFirst 涓嶆敮鎸佷唬鐮佸垱寤 tablespace 涓 schemas {tbname[0]}"); + if (string.Compare(tbname[0], userId) != 0 && _orm.Ado.ExecuteScalar(CommandType.Text, " select 1 from sys.dba_users where username={0}".FormatOracleSQL(tbname[0])) == null) //鍒涘缓鏁版嵁搴 + throw new NotImplementedException($"Oracle CodeFirst 涓嶆敮鎸佷唬鐮佸垱寤 tablespace 涓 schemas {tbname[0]}"); - var sbalter = new StringBuilder(); - var istmpatler = false; //鍒涘缓涓存椂琛紝瀵煎叆鏁版嵁锛屽垹闄ゆ棫琛紝淇敼 - if (ExecuteScalar(tbname[0], " select 1 from all_tab_comments where owner={0} and table_name={1}".FormatOracleSQL(tbname)) == null) { //琛ㄤ笉瀛樺湪 - if (tboldname != null) { - if (ExecuteScalar(tboldname[0], " select 1 from all_tab_comments where owner={0} and table_name={1}".FormatOracleSQL(tboldname)) == null) - //妯″紡鎴栬〃涓嶅瓨鍦 - tboldname = null; + var sbalter = new StringBuilder(); + var istmpatler = false; //鍒涘缓涓存椂琛紝瀵煎叆鏁版嵁锛屽垹闄ゆ棫琛紝淇敼 + if (_orm.Ado.ExecuteScalar(CommandType.Text, " select 1 from all_tab_comments where owner={0} and table_name={1}".FormatOracleSQL(tbname)) == null) { //琛ㄤ笉瀛樺湪 + if (tboldname != null) { + if (_orm.Ado.ExecuteScalar(CommandType.Text, " select 1 from all_tab_comments where owner={0} and table_name={1}".FormatOracleSQL(tboldname)) == null) + //妯″紡鎴栬〃涓嶅瓨鍦 + tboldname = null; + } + if (tboldname == null) { + //鍒涘缓琛 + sb.Append("execute immediate 'CREATE TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ("); + foreach (var tbcol in tb.Columns.Values) { + sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType).Append(","); + if (tbcol.Attribute.IsIdentity) seqcols.Add((tbcol, tbname, true)); } - if (tboldname == null) { - //鍒涘缓琛 - sb.Append("CREATE TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ("); - foreach (var tbcol in tb.Columns.Values) { - sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType).Append(","); - if (tbcol.Attribute.IsIdentity) seqcols.Add((tbcol, tbname, true)); - } - if (tb.Primarys.Any() == false) - sb.Remove(sb.Length - 1, 1); - else { - sb.Append(" \r\n CONSTRAINT ").Append(tbname[0]).Append("_").Append(tbname[1]).Append("_pk PRIMARY KEY ("); - foreach (var tbcol in tb.Primarys) sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", "); - sb.Remove(sb.Length - 2, 2).Append(")"); - } - sb.Append("\r\n) LOGGING \r\nNOCOMPRESS \r\nNOCACHE\r\n;\r\n"); - continue; - } - //濡傛灉鏂拌〃锛屾棫琛ㄥ湪涓涓ā寮忎笅锛岀洿鎺ヤ慨鏀硅〃鍚 - if (string.Compare(tbname[0], tboldname[0], true) == 0) - sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tboldname[0]}.{tboldname[1]}")).Append(" RENAME TO ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(";\r\n"); + if (tb.Primarys.Any() == false) + sb.Remove(sb.Length - 1, 1); else { - //濡傛灉鏂拌〃锛屾棫琛ㄤ笉鍦ㄤ竴璧凤紝鍒涘缓鏂拌〃锛屽鍏ユ暟鎹紝鍒犻櫎鏃ц〃 - istmpatler = true; + sb.Append(" \r\n CONSTRAINT ").Append(tbname[0]).Append("_").Append(tbname[1]).Append("_pk1 PRIMARY KEY ("); + foreach (var tbcol in tb.Primarys) sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", "); + sb.Remove(sb.Length - 2, 2).Append(")"); } - } else - tboldname = null; //濡傛灉鏂拌〃宸茬粡瀛樺湪锛屼笉璧版敼琛ㄥ悕閫昏緫 + sb.Append("\r\n) \r\nLOGGING \r\nNOCOMPRESS \r\nNOCACHE\r\n';\r\n"); + continue; + } + //濡傛灉鏂拌〃锛屾棫琛ㄥ湪涓涓ā寮忎笅锛岀洿鎺ヤ慨鏀硅〃鍚 + if (string.Compare(tbname[0], tboldname[0], true) == 0) + sbalter.Append("execute immediate 'ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tboldname[0]}.{tboldname[1]}")).Append(" RENAME TO ").Append(_commonUtils.QuoteSqlName($"{tbname[1]}")).Append("';\r\n"); + else { + //濡傛灉鏂拌〃锛屾棫琛ㄤ笉鍦ㄤ竴璧凤紝鍒涘缓鏂拌〃锛屽鍏ユ暟鎹紝鍒犻櫎鏃ц〃 + istmpatler = true; + } + } else + tboldname = null; //濡傛灉鏂拌〃宸茬粡瀛樺湪锛屼笉璧版敼琛ㄥ悕閫昏緫 - //瀵规瘮瀛楁锛屽彧鍙互淇敼绫诲瀷銆佸鍔犲瓧娈点佹湁闄愮殑淇敼瀛楁鍚嶏紱淇濊瘉瀹夊叏涓嶅垹闄ゅ瓧娈 - var addcols = new Dictionary(StringComparer.CurrentCultureIgnoreCase); - foreach (var tbcol in tb.Columns) addcols.Add(tbcol.Value.Attribute.Name, tbcol.Value); - var surplus = new Dictionary(StringComparer.CurrentCultureIgnoreCase); - var dbcols = new List(); - var sql = $@" + //瀵规瘮瀛楁锛屽彧鍙互淇敼绫诲瀷銆佸鍔犲瓧娈点佹湁闄愮殑淇敼瀛楁鍚嶏紱淇濊瘉瀹夊叏涓嶅垹闄ゅ瓧娈 + var sql = $@" select column_name, data_type, @@ -154,127 +137,136 @@ data_precision, data_scale, char_used, case when nullable = 'Y' then 1 else 0 end, -nvl((select 1 from user_sequences where sequence_name='{Utils.GetCsName(string.Join(".", tboldname ?? tbname))}_seq_'||all_tab_columns.column_name), 0) +nvl((select 1 from user_sequences where sequence_name='{Utils.GetCsName((tboldname ?? tbname).Last())}_seq_'||all_tab_columns.column_name), 0) from all_tab_columns where owner={{0}} and table_name={{1}}".FormatOracleSQL(tboldname ?? tbname); - var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql); - var tbstruct = ds.ToDictionary(a => string.Concat(a[0]), a => { - var sqlType = string.Concat(a[1]); - var data_length = long.Parse(string.Concat(a[2])); - long.TryParse(string.Concat(a[3]), out var data_precision); - long.TryParse(string.Concat(a[4]), out var data_scale); - var char_used = string.Concat(a[5]); - if (Regex.IsMatch(sqlType, @"INTERVAL DAY\(\d+\) TO SECOND\(\d+\)", RegexOptions.IgnoreCase)) { - } else if (Regex.IsMatch(sqlType, @"INTERVAL YEAR\(\d+\) TO MONTH", RegexOptions.IgnoreCase)) { - } else if (sqlType.StartsWith("TIMESTAMP", StringComparison.CurrentCultureIgnoreCase)) { - } else if (char_used.ToLower() == "c") { - sqlType += $"({data_length} CHAR)"; - } else if (char_used.ToLower() == "b") { - sqlType += $"({data_length} BYTE)"; - } else if (sqlType.ToLower() == "float") { - sqlType += $"({data_precision})"; - } else if (data_precision > 0 && data_scale > 0) { - sqlType += $"({data_precision},{data_scale})"; - } else { - sqlType += $"({data_length})"; - } - return new { - column = string.Concat(a[0]), - sqlType, - is_nullable = string.Concat(a[6]) == "1", - is_identity = string.Concat(a[7]) == "1" - }; - }, StringComparer.CurrentCultureIgnoreCase); + var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql); + var tbstruct = ds.ToDictionary(a => string.Concat(a[0]), a => { + var sqlType = string.Concat(a[1]); + var data_length = long.Parse(string.Concat(a[2])); + long.TryParse(string.Concat(a[3]), out var data_precision); + long.TryParse(string.Concat(a[4]), out var data_scale); + var char_used = string.Concat(a[5]); + switch(sqlType.ToUpper()) { + case "CHAR": data_length /= char_used.ToLower() == "c" ? 4 : 2; break; + } + if (Regex.IsMatch(sqlType, @"INTERVAL DAY\(\d+\) TO SECOND\(\d+\)", RegexOptions.IgnoreCase)) { + } else if (Regex.IsMatch(sqlType, @"INTERVAL YEAR\(\d+\) TO MONTH", RegexOptions.IgnoreCase)) { + } else if (sqlType.StartsWith("TIMESTAMP", StringComparison.CurrentCultureIgnoreCase)) { + } else if (char_used.ToLower() == "c") + sqlType += sqlType.StartsWith("N") ? $"({data_length / 2})" : $"({data_length / 4} CHAR)"; + else if (char_used.ToLower() == "b") + sqlType += $"({data_length} BYTE)"; + else if (sqlType.ToLower() == "float") + sqlType += $"({data_precision})"; + else if (data_precision > 0 && data_scale > 0) + sqlType += $"({data_precision},{data_scale})"; + else if (data_precision > 0) + sqlType += $"({data_precision})"; + else + sqlType += $"({data_length})"; + return new { + column = string.Concat(a[0]), + sqlType, + is_nullable = string.Concat(a[6]) == "1", + is_identity = string.Concat(a[7]) == "1" + }; + }, StringComparer.CurrentCultureIgnoreCase); - if (istmpatler == false) { - foreach (var tbcol in tb.Columns.Values) { - if (tbstruct.TryGetValue(tbcol.Attribute.Name, out var tbstructcol) || - string.IsNullOrEmpty(tbcol.Attribute.OldName) == false && tbstruct.TryGetValue(tbcol.Attribute.OldName, out tbstructcol)) { - if (tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType, StringComparison.CurrentCultureIgnoreCase) == false) - sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" MODIFY (").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" ").Append(tbcol.Attribute.DbType).Append(");\r\n"); - if (tbcol.Attribute.IsNullable != tbstructcol.is_nullable) { - if (tbcol.Attribute.IsNullable == false) - sbalter.Append("UPDATE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" SET ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(_commonUtils.FormatSql(" = {0}", tbcol.Attribute.DbDefautValue)).Append(" WHERE ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" IS NULL;\r\n"); - sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" MODIFY ").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" ").Append(tbcol.Attribute.IsNullable ? "" : "NOT").Append(" NULL;\r\n"); - } - if (tbcol.Attribute.IsIdentity != tbstructcol.is_identity) - seqcols.Add((tbcol, tbname, tbcol.Attribute.IsIdentity)); - if (tbstructcol.column == tbcol.Attribute.OldName) - //淇敼鍒楀悕 - sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" RENAME ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.OldName)).Append(" TO ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(";\r\n"); - continue; - } - //娣诲姞鍒 - sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ADD COLUMN ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType.Split(' ').First()).Append(";\r\n"); - sbalter.Append("UPDATE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" SET ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(_commonUtils.FormatSql(" = {0};\r\n", tbcol.Attribute.DbDefautValue)); - if (tbcol.Attribute.IsNullable == false) sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" MODIFY ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" NOT NULL;\r\n"); - if (tbcol.Attribute.IsIdentity) seqcols.Add((tbcol, tbname, tbcol.Attribute.IsIdentity)); - } - } - if (istmpatler == false) { - sb.Append(sbalter); - continue; - } - - //鍒涘缓涓存椂琛紝鏁版嵁瀵艰繘涓存椂琛紝鐒跺悗鍒犻櫎鍘熻〃锛屽皢涓存椂琛ㄦ敼鍚嶄负鍘熻〃鍚 - var tablename = tboldname == null ? _commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}") : _commonUtils.QuoteSqlName($"{tboldname[0]}.{tboldname[1]}"); - var tmptablename = _commonUtils.QuoteSqlName($"{tbname[0]}.FreeSqlTmp_{tbname[1]}"); - //鍒涘缓涓存椂琛 - sb.Append("CREATE TABLE ").Append(tmptablename).Append(" ("); + if (istmpatler == false) { foreach (var tbcol in tb.Columns.Values) { - sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType).Append(","); - if (tbcol.Attribute.IsIdentity) seqcols.Add((tbcol, tbname, true)); - } - if (tb.Primarys.Any() == false) - sb.Remove(sb.Length - 1, 1); - else { - sb.Append(" \r\n CONSTRAINT ").Append(tbname[0]).Append("_").Append(tbname[1]).Append("_pk PRIMARY KEY ("); - foreach (var tbcol in tb.Primarys) sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", "); - sb.Remove(sb.Length - 2, 2).Append(")"); - } - sb.Append("\r\n) LOGGING \r\nNOCOMPRESS \r\nNOCACHE\r\n;\r\n"); - sb.Append("INSERT INTO ").Append(tmptablename).Append(" ("); - foreach (var tbcol in tb.Columns.Values) - sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", "); - sb.Remove(sb.Length - 2, 2).Append(")\r\nSELECT "); - foreach (var tbcol in tb.Columns.Values) { - var insertvalue = "NULL"; + var dbtypeNoneNotNull = Regex.Replace(tbcol.Attribute.DbType, @"NOT\s+NULL", "NULL"); if (tbstruct.TryGetValue(tbcol.Attribute.Name, out var tbstructcol) || - string.IsNullOrEmpty(tbcol.Attribute.OldName) == false && tbstruct.TryGetValue(tbcol.Attribute.OldName, out tbstructcol)) { - insertvalue = _commonUtils.QuoteSqlName(tbstructcol.column); - if (tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType, StringComparison.CurrentCultureIgnoreCase) == false) { - //insertvalue = $"cast({insertvalue} as {tbcol.Attribute.DbType.Split(' ').First()})"; + string.IsNullOrEmpty(tbcol.Attribute.OldName) == false && tbstruct.TryGetValue(tbcol.Attribute.OldName, out tbstructcol)) { + if (tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType, StringComparison.CurrentCultureIgnoreCase) == false) + istmpatler = true; + //sbalter.Append("execute immediate 'ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" MODIFY (").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" ").Append(dbtypeNoneNotNull).Append(")';\r\n"); + if (tbcol.Attribute.IsNullable != tbstructcol.is_nullable) { + if (tbcol.Attribute.IsNullable == false) + sbalter.Append("execute immediate 'UPDATE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" SET ").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(_commonUtils.FormatSql(" = {0}", tbcol.Attribute.DbDefautValue).Replace("'", "''")).Append(" WHERE ").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" IS NULL';\r\n"); + sbalter.Append("execute immediate 'ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" MODIFY ").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" ").Append(tbcol.Attribute.IsNullable ? "" : "NOT").Append(" NULL';\r\n"); } - if (tbcol.Attribute.IsNullable != tbstructcol.is_nullable) - insertvalue = $"nvl({insertvalue},{_commonUtils.FormatSql("{0}", tbcol.Attribute.DbDefautValue).Replace("'", "''")})"; - } else if (tbcol.Attribute.IsNullable == false) - insertvalue = _commonUtils.FormatSql("{0}", tbcol.Attribute.DbDefautValue).Replace("'", "''"); - sb.Append(insertvalue).Append(", "); - } - sb.Remove(sb.Length - 2, 2).Append(" FROM ").Append(tablename).Append(";\r\n"); - sb.Append("DROP TABLE ").Append(tablename).Append(";\r\n"); - sb.Append("ALTER TABLE ").Append(tmptablename).Append(" RENAME TO ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(";\r\n"); - } - foreach (var seqcol in seqcols) { - var tbname = seqcol.Item2; - var seqname = Utils.GetCsName($"{tbname[0]}.{tbname[1]}_seq_{seqcol.Item1.Attribute.Name}"); - var tbname2 = _commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}"); - var colname2 = _commonUtils.QuoteSqlName(seqcol.Item1.Attribute.Name); - sb.Append("DROP SEQUENCE ").Append(seqname).Append(";\r\n"); - if (seqcol.Item3) { - var startWith = _orm.Ado.ExecuteScalar(CommandType.Text, $" select nvl({colname2},0) from {tbname2}"); - sb.Append("CREATE SEQUENCE ").Append(seqname).Append(" start with ").Append(startWith).Append(";\r\n"); + if (tbcol.Attribute.IsIdentity != tbstructcol.is_identity) + seqcols.Add((tbcol, tbname, tbcol.Attribute.IsIdentity)); + if (tbstructcol.column == tbcol.Attribute.OldName) + //淇敼鍒楀悕 + sbalter.Append("execute immediate 'ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" RENAME ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.OldName)).Append(" TO ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append("';\r\n"); + continue; + } + //娣诲姞鍒 + sbalter.Append("execute immediate 'ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ADD (").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(dbtypeNoneNotNull).Append(")';\r\n"); + if (tbcol.Attribute.IsNullable == false) { + sbalter.Append("execute immediate 'UPDATE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" SET ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(_commonUtils.FormatSql(" = {0}';\r\n", tbcol.Attribute.DbDefautValue).Replace("'", "''")); + sbalter.Append("execute immediate 'ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" MODIFY ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" NOT NULL';\r\n"); + } + if (tbcol.Attribute.IsIdentity) seqcols.Add((tbcol, tbname, tbcol.Attribute.IsIdentity)); } } - return sb.Length == 0 ? null : sb.ToString(); - } finally { - try { - conn.Value.ChangeDatabase(database); - _orm.Ado.MasterPool.Return(conn); - } catch { - _orm.Ado.MasterPool.Return(conn, true); + if (istmpatler == false) { + sb.Append(sbalter); + continue; + } + var oldpk = _orm.Ado.ExecuteScalar(CommandType.Text, @"select constraint_name from user_constraints where owner={0} and table_name={1} and constraint_type='P'".FormatPostgreSQL(tbname))?.ToString(); + if (string.IsNullOrEmpty(oldpk) == false) + sb.Append("execute immediate 'ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" DROP CONSTRAINT ").Append(oldpk).Append("';\r\n"); + + //鍒涘缓涓存椂琛紝鏁版嵁瀵艰繘涓存椂琛紝鐒跺悗鍒犻櫎鍘熻〃锛屽皢涓存椂琛ㄦ敼鍚嶄负鍘熻〃鍚 + var tablename = tboldname == null ? _commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}") : _commonUtils.QuoteSqlName($"{tboldname[0]}.{tboldname[1]}"); + var tmptablename = _commonUtils.QuoteSqlName($"{tbname[0]}.FreeSqlTmp_{tbname[1]}"); + //鍒涘缓涓存椂琛 + sb.Append("execute immediate 'CREATE TABLE ").Append(tmptablename).Append(" ("); + foreach (var tbcol in tb.Columns.Values) { + sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType).Append(","); + if (tbcol.Attribute.IsIdentity) seqcols.Add((tbcol, tbname, true)); + } + if (tb.Primarys.Any() == false) + sb.Remove(sb.Length - 1, 1); + else { + sb.Append(" \r\n CONSTRAINT ").Append(tbname[0]).Append("_").Append(tbname[1]).Append("_pk2 PRIMARY KEY ("); + foreach (var tbcol in tb.Primarys) sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", "); + sb.Remove(sb.Length - 2, 2).Append(")"); + } + sb.Append("\r\n) LOGGING \r\nNOCOMPRESS \r\nNOCACHE\r\n';\r\n"); + sb.Append("execute immediate 'INSERT INTO ").Append(tmptablename).Append(" ("); + foreach (var tbcol in tb.Columns.Values) + sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", "); + sb.Remove(sb.Length - 2, 2).Append(")\r\nSELECT "); + foreach (var tbcol in tb.Columns.Values) { + var insertvalue = "NULL"; + if (tbstruct.TryGetValue(tbcol.Attribute.Name, out var tbstructcol) || + string.IsNullOrEmpty(tbcol.Attribute.OldName) == false && tbstruct.TryGetValue(tbcol.Attribute.OldName, out tbstructcol)) { + insertvalue = _commonUtils.QuoteSqlName(tbstructcol.column); + if (tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType, StringComparison.CurrentCultureIgnoreCase) == false) { + var dbtypeNoneNotNull = Regex.Replace(tbcol.Attribute.DbType, @"(NOT\s+)?NULL", ""); + insertvalue = $"cast({insertvalue} as {dbtypeNoneNotNull})"; + } + if (tbcol.Attribute.IsNullable != tbstructcol.is_nullable) + insertvalue = $"nvl({insertvalue},{_commonUtils.FormatSql("{0}", tbcol.Attribute.DbDefautValue)})"; + } else if (tbcol.Attribute.IsNullable == false) + insertvalue = _commonUtils.FormatSql("{0}", tbcol.Attribute.DbDefautValue); + sb.Append(insertvalue.Replace("'", "''")).Append(", "); + } + sb.Remove(sb.Length - 2, 2).Append(" FROM ").Append(tablename).Append("';\r\n"); + sb.Append("execute immediate 'DROP TABLE ").Append(tablename).Append("';\r\n"); + sb.Append("execute immediate 'ALTER TABLE ").Append(tmptablename).Append(" RENAME TO ").Append(_commonUtils.QuoteSqlName($"{tbname[1]}")).Append("';\r\n"); + } + foreach (var seqcol in seqcols) { + var tbname = seqcol.Item2; + var seqname = Utils.GetCsName($"{tbname[1]}_seq_{seqcol.Item1.Attribute.Name}"); + var tbname2 = _commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}"); + var colname2 = _commonUtils.QuoteSqlName(seqcol.Item1.Attribute.Name); + sbDeclare.Append("declare ").Append(seqname).Append("_exists NUMBER; \r\n"); + sb.Append(seqname).Append("_exists := 0; \r\n") + .Append(" select count(1) into ").Append(seqname).Append("_exists from user_sequences where sequence_name={0}; \r\n".FormatOracleSQL(seqname)) + .Append("if ").Append(seqname).Append("_exists > 0 then \r\n") + .Append(" execute immediate 'DROP SEQUENCE ").Append(_commonUtils.QuoteSqlName(seqname)).Append("';\r\n") + .Append("end if; \r\n"); + if (seqcol.Item3) { + var startWith = _orm.Ado.ExecuteScalar(CommandType.Text, $" select nvl(max({colname2})+1,1) from {tbname2}"); + sb.Append("execute immediate 'CREATE SEQUENCE ").Append(_commonUtils.QuoteSqlName(seqname)).Append(" start with ").Append(startWith).Append("';\r\n"); } } + return sb.Length == 0 ? null : sb.Insert(0, "BEGIN \r\n").Insert(0, sbDeclare.ToString()).Append("END;").ToString(); } ConcurrentDictionary dicSyced = new ConcurrentDictionary(); diff --git a/FreeSql/Oracle/OracleUtils.cs b/FreeSql/Oracle/OracleUtils.cs index 6e6a095c..5128a814 100644 --- a/FreeSql/Oracle/OracleUtils.cs +++ b/FreeSql/Oracle/OracleUtils.cs @@ -16,7 +16,7 @@ namespace FreeSql.Oracle { internal override DbParameter AppendParamter(List _params, string parameterName, Type type, object value) { if (string.IsNullOrEmpty(parameterName)) parameterName = $"p_{_params?.Count}"; else if (_orm.CodeFirst.IsSyncStructureToLower) parameterName = parameterName.ToLower(); - var ret = new OracleParameter { ParameterName = $"@{parameterName}", Value = value }; + var ret = new OracleParameter { ParameterName = $":{parameterName}", Value = value }; var tp = _orm.CodeFirst.GetDbInfo(type)?.type; if (tp != null) { ret.OracleDbType = (OracleDbType)tp.Value; @@ -26,8 +26,8 @@ namespace FreeSql.Oracle { } internal override DbParameter[] GetDbParamtersByObject(string sql, object obj) => - Utils.GetDbParamtersByObject(sql, obj, "@", (name, type, value) => { - var ret = new OracleParameter { ParameterName = $"@{name}", Value = value }; + Utils.GetDbParamtersByObject(sql, obj, ":", (name, type, value) => { + var ret = new OracleParameter { ParameterName = $":{name}", Value = value }; var tp = _orm.CodeFirst.GetDbInfo(type)?.type; if (tp != null) { ret.OracleDbType = (OracleDbType)tp.Value; @@ -37,7 +37,7 @@ namespace FreeSql.Oracle { internal override string FormatSql(string sql, params object[] args) => sql?.FormatOracleSQL(args); internal override string QuoteSqlName(string name) => $"\"{name.Trim('"').Replace(".", "\".\"")}\""; - internal override string QuoteParamterName(string name) => $"@{(_orm.CodeFirst.IsSyncStructureToLower ? name.ToLower() : name)}"; + internal override string QuoteParamterName(string name) => $":{(_orm.CodeFirst.IsSyncStructureToLower ? name.ToLower() : name)}"; internal override string IsNull(string sql, object value) => $"nvl({sql}, {value})"; internal override string StringConcat(string left, string right, Type leftType, Type rightType) => $"{left} || {right}"; diff --git a/FreeSql/PostgreSQL/PostgreSQLCodeFirst.cs b/FreeSql/PostgreSQL/PostgreSQLCodeFirst.cs index 96a68414..0383fdec 100644 --- a/FreeSql/PostgreSQL/PostgreSQLCodeFirst.cs +++ b/FreeSql/PostgreSQL/PostgreSQLCodeFirst.cs @@ -241,6 +241,14 @@ where ns.nspname = {0} and c.relname = {1}".FormatPostgreSQL(tboldname ?? tbname sb.Append(sbalter); continue; } + var oldpk = _orm.Ado.ExecuteScalar(CommandType.Text, @"select pg_constraint.conname as pk_name from pg_constraint +inner join pg_class on pg_constraint.conrelid = pg_class.oid +inner join pg_namespace on pg_namespace.oid = pg_class.relnamespace +where pg_namespace.nspname={0} and pg_class.relname={1} and pg_constraint.contype='p' +".FormatPostgreSQL(tbname))?.ToString(); + if (string.IsNullOrEmpty(oldpk) == false) + sb.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" DROP CONSTRAINT ").Append(oldpk).Append(";\r\n"); + //鍒涘缓涓存椂琛紝鏁版嵁瀵艰繘涓存椂琛紝鐒跺悗鍒犻櫎鍘熻〃锛屽皢涓存椂琛ㄦ敼鍚嶄负鍘熻〃鍚 var tablename = tboldname == null ? _commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}") : _commonUtils.QuoteSqlName($"{tboldname[0]}.{tboldname[1]}"); var tmptablename = _commonUtils.QuoteSqlName($"{tbname[0]}.FreeSqlTmp_{tbname[1]}"); @@ -270,9 +278,9 @@ where ns.nspname = {0} and c.relname = {1}".FormatPostgreSQL(tboldname ?? tbname if (tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType, StringComparison.CurrentCultureIgnoreCase) == false) insertvalue = $"cast({insertvalue} as {tbcol.Attribute.DbType.Split(' ').First()})"; if (tbcol.Attribute.IsNullable != tbstructcol.is_nullable) - insertvalue = $"coalesce({insertvalue},{_commonUtils.FormatSql("{0}", tbcol.Attribute.DbDefautValue).Replace("'", "''")})"; + insertvalue = $"coalesce({insertvalue},{_commonUtils.FormatSql("{0}", tbcol.Attribute.DbDefautValue)})"; } else if (tbcol.Attribute.IsNullable == false) - insertvalue = _commonUtils.FormatSql("{0}", tbcol.Attribute.DbDefautValue).Replace("'", "''"); + insertvalue = _commonUtils.FormatSql("{0}", tbcol.Attribute.DbDefautValue); sb.Append(insertvalue).Append(", "); } sb.Remove(sb.Length - 2, 2).Append(" FROM ").Append(tablename).Append(";\r\n"); diff --git a/FreeSql/SqlServer/SqlServerCodeFirst.cs b/FreeSql/SqlServer/SqlServerCodeFirst.cs index da4cb616..6f0c11f1 100644 --- a/FreeSql/SqlServer/SqlServerCodeFirst.cs +++ b/FreeSql/SqlServer/SqlServerCodeFirst.cs @@ -239,9 +239,9 @@ use " + database, tboldname ?? tbname); if (tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType, StringComparison.CurrentCultureIgnoreCase) == false) insertvalue = $"cast({insertvalue} as {tbcol.Attribute.DbType.Split(' ').First()})"; if (tbcol.Attribute.IsNullable != tbstructcol.is_nullable) - insertvalue = $"isnull({insertvalue},{_commonUtils.FormatSql("{0}", tbcol.Attribute.DbDefautValue).Replace("'", "''")})"; + insertvalue = $"isnull({insertvalue},{_commonUtils.FormatSql("{0}", tbcol.Attribute.DbDefautValue)})"; } else if (tbcol.Attribute.IsNullable == false) - insertvalue = _commonUtils.FormatSql("{0}", tbcol.Attribute.DbDefautValue).Replace("'", "''"); + insertvalue = _commonUtils.FormatSql("{0}", tbcol.Attribute.DbDefautValue); sb.Append(insertvalue).Append(", "); } sb.Remove(sb.Length - 2, 2).Append(" FROM ").Append(tablename).Append(" WITH (HOLDLOCK TABLOCKX)');\r\n");