diff --git a/FreeSql.Tests/MySql/MySqlCodeFirstTest.cs b/FreeSql.Tests/MySql/MySqlCodeFirstTest.cs index 4e546f8b..90673eca 100644 --- a/FreeSql.Tests/MySql/MySqlCodeFirstTest.cs +++ b/FreeSql.Tests/MySql/MySqlCodeFirstTest.cs @@ -45,11 +45,11 @@ namespace FreeSql.Tests.MySql { [Column(Unique = "uk_phone")] public string phone { get; set; } - [Column(Unique = "uk_group_index")] + [Column(Unique = "uk_group_index, uk_group_index22")] public string group { get; set; } - [Column(Unique = "uk_group_index11")] + [Column(Unique = "uk_group_index")] public int index { get; set; } - [Column(Unique = "uk_group_index222")] + [Column(Unique = "uk_group_index22")] public string index22 { get; set; } } diff --git a/FreeSql.Tests/Oracle/OracleCodeFirstTest.cs b/FreeSql.Tests/Oracle/OracleCodeFirstTest.cs index 8fbe5f20..5bf2a0d3 100644 --- a/FreeSql.Tests/Oracle/OracleCodeFirstTest.cs +++ b/FreeSql.Tests/Oracle/OracleCodeFirstTest.cs @@ -45,11 +45,11 @@ namespace FreeSql.Tests.Oracle { [Column(Unique = "uk_phone")] public string phone { get; set; } - [Column(Unique = "uk_group_index")] + [Column(Unique = "uk_group_index, uk_group_index22")] public string group { get; set; } - [Column(Unique = "uk_group_index11")] + [Column(Unique = "uk_group_index")] public int index { get; set; } - [Column(Unique = "uk_group_index222")] + [Column(Unique = "uk_group_index22")] public string index22 { get; set; } } [Fact] diff --git a/FreeSql.Tests/PostgreSQL/PostgreSQLCodeFirstTest.cs b/FreeSql.Tests/PostgreSQL/PostgreSQLCodeFirstTest.cs index b8cb972c..423dd33c 100644 --- a/FreeSql.Tests/PostgreSQL/PostgreSQLCodeFirstTest.cs +++ b/FreeSql.Tests/PostgreSQL/PostgreSQLCodeFirstTest.cs @@ -52,11 +52,11 @@ namespace FreeSql.Tests.PostgreSQL { [Column(Unique = "uk_phone")] public string phone { get; set; } - [Column(Unique = "uk_group_index")] + [Column(Unique = "uk_group_index, uk_group_index22")] public string group { get; set; } - [Column(Unique = "uk_group_index11")] + [Column(Unique = "uk_group_index")] public int index { get; set; } - [Column(Unique = "uk_group_index222")] + [Column(Unique = "uk_group_index22")] public string index22 { get; set; } } diff --git a/FreeSql.Tests/SqlServer/SqlServerCodeFirstTest.cs b/FreeSql.Tests/SqlServer/SqlServerCodeFirstTest.cs index 23227114..7d097c0d 100644 --- a/FreeSql.Tests/SqlServer/SqlServerCodeFirstTest.cs +++ b/FreeSql.Tests/SqlServer/SqlServerCodeFirstTest.cs @@ -56,11 +56,11 @@ namespace FreeSql.Tests.SqlServer { [Column(Unique = "uk_phone")] public string phone { get; set; } - [Column(Unique = "uk_group_index")] + [Column(Unique = "uk_group_index, uk_group_index22")] public string group { get; set; } - [Column(Unique = "uk_group_index11")] + [Column(Unique = "uk_group_index")] public int index { get; set; } - [Column(Unique = "uk_group_index222")] + [Column(Unique = "uk_group_index22")] public string index22 { get; set; } } diff --git a/FreeSql.Tests/Sqlite/SqliteCodeFirstTest.cs b/FreeSql.Tests/Sqlite/SqliteCodeFirstTest.cs index ae7389e9..b6a3e8bd 100644 --- a/FreeSql.Tests/Sqlite/SqliteCodeFirstTest.cs +++ b/FreeSql.Tests/Sqlite/SqliteCodeFirstTest.cs @@ -45,11 +45,11 @@ namespace FreeSql.Tests.Sqlite { [Column(Unique = "uk_phone")] public string phone { get; set; } - [Column(Unique = "uk_group_index")] + [Column(Unique = "uk_group_index, uk_group_index22")] public string group { get; set; } - [Column(Unique = "uk_group_index111")] + [Column(Unique = "uk_group_index")] public int index { get; set; } - [Column(Unique = "uk_group_index222")] + [Column(Unique = "uk_group_index22")] public string index22 { get; set; } } diff --git a/FreeSql/DataAnnotations/ColumnAttribute.cs b/FreeSql/DataAnnotations/ColumnAttribute.cs index c3b4d018..df5c9835 100644 --- a/FreeSql/DataAnnotations/ColumnAttribute.cs +++ b/FreeSql/DataAnnotations/ColumnAttribute.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; namespace FreeSql.DataAnnotations { public class ColumnAttribute : Attribute { @@ -38,10 +39,30 @@ namespace FreeSql.DataAnnotations { /// public bool IsVersion { get => _IsVersion ?? false; set => _IsVersion = value; } + internal string[] _Uniques; /// - /// 唯一键,多个属性指定相同的标识,代表联合键 + /// 唯一键,在多个属性指定相同的标识,代表联合键;可使用逗号分割多个 UniqueKey 名。 /// - public string Unique { get; set; } + public string Unique { + get => _Uniques == null ? null : string.Join(", ", _Uniques); + set { + if (string.IsNullOrEmpty(value)) { + _Uniques = null; + return; + } + var val = value?.Trim(' ', '\t', ','); + if (string.IsNullOrEmpty(val)) { + _Uniques = null; + return; + } + var arr = val.Split(',').Select(a => a.Trim(' ', '\t').Trim()).Where(a => !string.IsNullOrEmpty(a)).ToArray(); + if (arr.Any() == false) { + _Uniques = null; + return; + } + _Uniques = arr; + } + } /// /// 数据库默认值 /// diff --git a/FreeSql/DataAnnotations/ColumnFluent.cs b/FreeSql/DataAnnotations/ColumnFluent.cs index 8fa9c6dc..6894cde1 100644 --- a/FreeSql/DataAnnotations/ColumnFluent.cs +++ b/FreeSql/DataAnnotations/ColumnFluent.cs @@ -66,7 +66,7 @@ namespace FreeSql.DataAnnotations { return this; } /// - /// 唯一键,多个属性指定相同的标识,代表联合键 + /// 唯一键,在多个属性指定相同的标识,代表联合键;可使用逗号分割多个 UniqueKey 名。 /// /// 标识 /// diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml index 0a5b20d3..f45283ac 100644 --- a/FreeSql/FreeSql.xml +++ b/FreeSql/FreeSql.xml @@ -46,7 +46,7 @@ - 唯一键,多个属性指定相同的标识,代表联合键 + 唯一键,在多个属性指定相同的标识,代表联合键;可使用逗号分割多个 UniqueKey 名。 @@ -101,7 +101,7 @@ - 唯一键,多个属性指定相同的标识,代表联合键 + 唯一键,在多个属性指定相同的标识,代表联合键;可使用逗号分割多个 UniqueKey 名。 标识 diff --git a/FreeSql/Internal/CommonUtils.cs b/FreeSql/Internal/CommonUtils.cs index fe9ef4f9..91f32308 100644 --- a/FreeSql/Internal/CommonUtils.cs +++ b/FreeSql/Internal/CommonUtils.cs @@ -101,7 +101,7 @@ namespace FreeSql.Internal { if (trycol._IsNullable != null) attr._IsNullable = trycol.IsNullable; if (trycol._IsIgnore != null) attr._IsIgnore = trycol.IsIgnore; if (trycol._IsVersion != null) attr._IsVersion = trycol.IsVersion; - if (!string.IsNullOrEmpty(trycol.Unique)) attr.Unique = trycol.Unique; + if (trycol._Uniques != null) attr._Uniques = trycol._Uniques; if (trycol.MapType != null) attr.MapType = trycol.MapType; if (trycol.DbDefautValue != null) attr.DbDefautValue = trycol.DbDefautValue; } @@ -117,7 +117,7 @@ namespace FreeSql.Internal { if (tryattr._IsNullable != null) attr._IsNullable = tryattr.IsNullable; if (tryattr._IsIgnore != null) attr._IsIgnore = tryattr.IsIgnore; if (tryattr._IsVersion != null) attr._IsVersion = tryattr.IsVersion; - if (!string.IsNullOrEmpty(tryattr.Unique)) attr.Unique = tryattr.Unique; + if (tryattr._Uniques != null) attr._Uniques = tryattr._Uniques; if (tryattr.MapType != null) attr.MapType = tryattr.MapType; if (tryattr.DbDefautValue != null) attr.DbDefautValue = tryattr.DbDefautValue; } @@ -130,7 +130,7 @@ namespace FreeSql.Internal { if (attr._IsNullable != null) ret = attr; if (attr._IsIgnore != null) ret = attr; if (attr._IsVersion != null) ret = attr; - if (!string.IsNullOrEmpty(attr.Unique)) ret = attr; + if (attr._Uniques != null) ret = attr; if (attr.MapType != null) ret = attr; if (attr.DbDefautValue != null) ret = attr; if (ret != null && ret.MapType == null) ret.MapType = proto.PropertyType; diff --git a/FreeSql/Internal/UtilsExpressionTree.cs b/FreeSql/Internal/UtilsExpressionTree.cs index 31660038..79b4202e 100644 --- a/FreeSql/Internal/UtilsExpressionTree.cs +++ b/FreeSql/Internal/UtilsExpressionTree.cs @@ -91,11 +91,11 @@ namespace FreeSql.Internal { if (string.IsNullOrEmpty(colattr.Name)) colattr.Name = p.Name; if (common.CodeFirst.IsSyncStructureToLower) { colattr.Name = colattr.Name.ToLower(); - if (!string.IsNullOrEmpty(colattr.Unique)) colattr.Unique = colattr.Unique.ToLower(); + colattr.Unique = colattr.Unique?.ToLower(); } if (common.CodeFirst.IsSyncStructureToUpper) { colattr.Name = colattr.Name.ToUpper(); - if (!string.IsNullOrEmpty(colattr.Unique)) colattr.Unique = colattr.Unique.ToUpper(); + colattr.Unique = colattr.Unique?.ToUpper(); } if ((colattr.IsNullable != true || colattr.IsIdentity == true || colattr.IsPrimary == true) && colattr.DbType.Contains("NOT NULL") == false) { @@ -179,7 +179,8 @@ namespace FreeSql.Internal { foreach (var dbcol in dbuk.Value) { if (trytb.Columns.TryGetValue(dbcol.Name, out var trycol) && trycol.Attribute.MapType == dbcol.CsType || trytb.ColumnsByCs.TryGetValue(dbcol.Name, out trycol) && trycol.Attribute.MapType == dbcol.CsType) { - trycol.Attribute.Unique = dbuk.Key; + if (trycol.Attribute._Uniques?.Contains(dbuk.Key) != true) + trycol.Attribute.Unique += $"," + dbuk.Key; } } } @@ -188,8 +189,8 @@ namespace FreeSql.Internal { } catch { } trytb.Primarys = trytb.Columns.Values.Where(a => a.Attribute.IsPrimary == true).ToArray(); } - trytb.Uniques = trytb.Columns.Values.Where(a => !string.IsNullOrEmpty(a.Attribute.Unique)).Select(a => a.Attribute.Unique).Distinct() - .ToDictionary(a => a, a => trytb.Columns.Values.Where(b => b.Attribute.Unique == a).ToList()); + var allunique = trytb.Columns.Values.Where(a => a.Attribute._Uniques != null).SelectMany(a => a.Attribute._Uniques).Distinct(); + trytb.Uniques = allunique.ToDictionary(a => a, a => trytb.Columns.Values.Where(b => b.Attribute._Uniques != null && b.Attribute._Uniques.Contains(a)).ToList()); tbc.AddOrUpdate(entity, trytb, (oldkey, oldval) => trytb); #region 查找导航属性的关系、virtual 属性延时加载,动态产生新的重写类