- 增加 IndexAttribute 特性,自动迁移索引,以及对应的 FluentApi 方法;

- 移除 ColumnAttribute.Unique 属性设置,改为 IndexAttribute 特性设置唯一键;
This commit is contained in:
28810
2019-10-03 04:31:04 +08:00
parent cb18b74830
commit 78fded3f8e
43 changed files with 1010 additions and 607 deletions

View File

@ -3,6 +3,7 @@ using System.Linq;
namespace FreeSql.DataAnnotations
{
[AttributeUsage(AttributeTargets.Property)]
public class ColumnAttribute : Attribute
{
@ -42,35 +43,6 @@ namespace FreeSql.DataAnnotations
/// </summary>
public bool IsVersion { get => _IsVersion ?? false; set => _IsVersion = value; }
internal string[] _Uniques;
/// <summary>
/// 唯一键,在多个属性指定相同的标识,代表联合键;可使用逗号分割多个 UniqueKey 名。
/// </summary>
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;
}
}
/// <summary>
/// 数据库默认值
/// </summary>

View File

@ -77,16 +77,6 @@ namespace FreeSql.DataAnnotations
return this;
}
/// <summary>
/// 唯一键,在多个属性指定相同的标识,代表联合键;可使用逗号分割多个 UniqueKey 名。
/// </summary>
/// <param name="value">标识</param>
/// <returns></returns>
public ColumnFluent Unique(string value)
{
_column.Unique = value;
return this;
}
/// <summary>
/// 类型映射,比如:可将 enum 属性映射成 typeof(string)
/// </summary>
/// <param name="value"></param>

View File

@ -1,8 +1,10 @@
using System;
using System.Collections.Concurrent;
using System.Linq.Expressions;
namespace FreeSql.DataAnnotations
{
[AttributeUsage(AttributeTargets.Class)]
public class TableAttribute : Attribute
{
@ -27,5 +29,36 @@ namespace FreeSql.DataAnnotations
internal ConcurrentDictionary<string, ColumnAttribute> _columns { get; } = new ConcurrentDictionary<string, ColumnAttribute>(StringComparer.CurrentCultureIgnoreCase);
internal ConcurrentDictionary<string, NavigateAttribute> _navigates { get; } = new ConcurrentDictionary<string, NavigateAttribute>(StringComparer.CurrentCultureIgnoreCase);
internal ConcurrentDictionary<string, IndexAttribute> _indexs { get; } = new ConcurrentDictionary<string, IndexAttribute>(StringComparer.CurrentCultureIgnoreCase);
}
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class IndexAttribute : Attribute
{
public IndexAttribute(string name, string fields)
{
this.Name = name;
this.Fields = fields;
}
public IndexAttribute(string name, string fields, bool isUnique)
{
this.Name = name;
this.Fields = fields;
this.IsUnique = isUnique;
}
/// <summary>
/// 索引名
/// </summary>
public string Name { get; set; }
/// <summary>
/// 索引字段为属性名以逗号分隔Create_time ASC, Title ASC
/// </summary>
public string Fields { get; set; }
internal bool? _IsUnique;
/// <summary>
/// 是否唯一
/// </summary>
public bool IsUnique { get => _IsUnique ?? false; set => _IsUnique = value; }
}
}

View File

@ -59,6 +59,20 @@ namespace FreeSql.DataAnnotations
var col = _table._columns.GetOrAdd(proto, name => new ColumnAttribute { Name = proto });
return new ColumnFluent(col);
}
/// <summary>
/// 设置实体的索引
/// </summary>
/// <param name="name">索引名</param>
/// <param name="fields">索引字段为属性名以逗号分隔Create_time ASC, Title ASC</param>
/// <param name="isUnique">是否唯一</param>
/// <returns></returns>
public TableFluent Index(string name, string fields, bool isUnique = false)
{
var idx = new IndexAttribute(name, fields, isUnique);
_table._indexs.AddOrUpdate(name, idx, (_, __) => idx);
return this;
}
}
public class TableFluent<T>
@ -128,5 +142,19 @@ namespace FreeSql.DataAnnotations
_table._navigates.AddOrUpdate(member.Name, nav, (name, old) => nav);
return this;
}
/// <summary>
/// 设置实体的索引
/// </summary>
/// <param name="name">索引名</param>
/// <param name="fields">索引字段为属性名以逗号分隔Create_time ASC, Title ASC</param>
/// <param name="isUnique">是否唯一</param>
/// <returns></returns>
public TableFluent<T> Index(string name, string fields, bool isUnique = false)
{
var idx = new IndexAttribute(name, fields, isUnique);
_table._indexs.AddOrUpdate(name, idx, (_, __) => idx);
return this;
}
}
}

View File

@ -40,18 +40,18 @@ namespace FreeSql.DatabaseModel
/// <summary>
/// 唯一键/组合
/// </summary>
public Dictionary<string, List<DbColumnInfo>> UniquesDict { get; set; } = new Dictionary<string, List<DbColumnInfo>>();
public Dictionary<string, DbIndexInfo> UniquesDict { get; set; } = new Dictionary<string, DbIndexInfo>();
/// <summary>
/// 索引/组合
/// </summary>
public Dictionary<string, List<DbColumnInfo>> IndexesDict { get; set; } = new Dictionary<string, List<DbColumnInfo>>();
public Dictionary<string, DbIndexInfo> IndexesDict { get; set; } = new Dictionary<string, DbIndexInfo>();
/// <summary>
/// 外键
/// </summary>
public Dictionary<string, DbForeignInfo> ForeignsDict { get; set; } = new Dictionary<string, DbForeignInfo>();
public List<List<DbColumnInfo>> Uniques => UniquesDict.Values.ToList();
public List<List<DbColumnInfo>> Indexes => IndexesDict.Values.ToList();
public List<DbIndexInfo> Uniques => UniquesDict.Values.ToList();
public List<DbIndexInfo> Indexes => IndexesDict.Values.ToList();
public List<DbForeignInfo> Foreigns => ForeignsDict.Values.ToList();
}

View File

@ -0,0 +1,21 @@
using FreeSql.DataAnnotations;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq.Expressions;
namespace FreeSql.DatabaseModel
{
public class DbIndexInfo
{
public string Name { get; set; }
public List<DbIndexColumnInfo> Columns { get; } = new List<DbIndexColumnInfo>();
public bool IsUnique { get; set; }
}
public class DbIndexColumnInfo
{
public DbColumnInfo Column { get; set; }
public bool IsDesc { get; set; }
}
}

View File

@ -45,11 +45,6 @@
设置行锁(乐观锁)版本号,每次更新累加版本号,若更新整个实体时会附带当前的版本号判断(修改失败时抛出异常)
</summary>
</member>
<member name="P:FreeSql.DataAnnotations.ColumnAttribute.Unique">
<summary>
唯一键,在多个属性指定相同的标识,代表联合键;可使用逗号分割多个 UniqueKey 名。
</summary>
</member>
<member name="P:FreeSql.DataAnnotations.ColumnAttribute.DbDefautValue">
<summary>
数据库默认值
@ -123,13 +118,6 @@
乐观锁
</summary>
</member>
<member name="M:FreeSql.DataAnnotations.ColumnFluent.Unique(System.String)">
<summary>
唯一键,在多个属性指定相同的标识,代表联合键;可使用逗号分割多个 UniqueKey 名。
</summary>
<param name="value">标识</param>
<returns></returns>
</member>
<member name="M:FreeSql.DataAnnotations.ColumnFluent.MapType(System.Type)">
<summary>
类型映射,比如:可将 enum 属性映射成 typeof(string)
@ -199,6 +187,21 @@
禁用 CodeFirst 同步结构迁移
</summary>
</member>
<member name="P:FreeSql.DataAnnotations.IndexAttribute.Name">
<summary>
索引名
</summary>
</member>
<member name="P:FreeSql.DataAnnotations.IndexAttribute.Fields">
<summary>
索引字段为属性名以逗号分隔Create_time ASC, Title ASC
</summary>
</member>
<member name="P:FreeSql.DataAnnotations.IndexAttribute.IsUnique">
<summary>
是否唯一
</summary>
</member>
<member name="M:FreeSql.DataAnnotations.TableFluent.Name(System.String)">
<summary>
数据库表名
@ -219,6 +222,15 @@
禁用 CodeFirst 同步结构迁移
</summary>
</member>
<member name="M:FreeSql.DataAnnotations.TableFluent.Index(System.String,System.String,System.Boolean)">
<summary>
设置实体的索引
</summary>
<param name="name">索引名</param>
<param name="fields">索引字段为属性名以逗号分隔Create_time ASC, Title ASC</param>
<param name="isUnique">是否唯一</param>
<returns></returns>
</member>
<member name="M:FreeSql.DataAnnotations.TableFluent`1.Name(System.String)">
<summary>
数据库表名
@ -249,6 +261,15 @@
<param name="manyToMany">多对多关系的中间实体类型</param>
<returns></returns>
</member>
<member name="M:FreeSql.DataAnnotations.TableFluent`1.Index(System.String,System.String,System.Boolean)">
<summary>
设置实体的索引
</summary>
<param name="name">索引名</param>
<param name="fields">索引字段为属性名以逗号分隔Create_time ASC, Title ASC</param>
<param name="isUnique">是否唯一</param>
<returns></returns>
</member>
<member name="P:FreeSql.DatabaseModel.DbColumnInfo.Table">
<summary>
所属表
@ -551,7 +572,9 @@
</member>
<member name="M:FreeSql.FreeSqlBuilder.UseConfigEntityFromDbFirst(System.Boolean)">
<summary>
使用数据库的主键自增,适用 DbFirst 模式,无须在实体类型上设置 [Column(IsPrimary)] 或者 ConfigEntity。此功能目前可用于 mysql/sqlserver/postgresql
数据库的主键自增、索引设置导入,适用 DbFirst 模式,无须在实体类型上设置 [Column(IsPrimary)] 或者 ConfigEntity。此功能目前可用于 mysql/sqlserver/postgresql/oracle。<para></para>
本功能会影响 IFreeSql 首次访问的速度。<para></para>
若使用 CodeFirst 创建索引后,又直接在数据库上建了索引,若无本功能下一次 CodeFirst 迁移时数据库上创建的索引将被删除
</summary>
<param name="value"></param>
<returns></returns>
@ -2288,7 +2311,9 @@
</member>
<member name="P:FreeSql.ICodeFirst.IsConfigEntityFromDbFirst">
<summary>
使用数据库的主键自增,适用 DbFirst 模式,无须在实体类型上设置 [Column(IsPrimary)] 或者 ConfigEntity。此功能目前可用于 mysql/sqlserver/postgresql
数据库的主键自增、索引设置导入,适用 DbFirst 模式,无须在实体类型上设置 [Column(IsPrimary)] 或者 ConfigEntity。此功能目前可用于 mysql/sqlserver/postgresql/oracle。<para></para>
本功能会影响 IFreeSql 首次访问的速度。<para></para>
若使用 CodeFirst 创建索引后,又直接在数据库上建了索引,若无本功能下一次 CodeFirst 迁移时数据库上创建的索引将被删除
</summary>
</member>
<member name="P:FreeSql.ICodeFirst.IsNoneCommandParameter">

View File

@ -78,7 +78,9 @@ namespace FreeSql
return this;
}
/// <summary>
/// 使用数据库的主键自增,适用 DbFirst 模式,无须在实体类型上设置 [Column(IsPrimary)] 或者 ConfigEntity。此功能目前可用于 mysql/sqlserver/postgresql
/// 数据库的主键自增、索引设置导入,适用 DbFirst 模式,无须在实体类型上设置 [Column(IsPrimary)] 或者 ConfigEntity。此功能目前可用于 mysql/sqlserver/postgresql/oracle。<para></para>
/// 本功能会影响 IFreeSql 首次访问的速度。<para></para>
/// 若使用 CodeFirst 创建索引后,又直接在数据库上建了索引,若无本功能下一次 CodeFirst 迁移时数据库上创建的索引将被删除
/// </summary>
/// <param name="value"></param>
/// <returns></returns>

View File

@ -21,7 +21,9 @@ namespace FreeSql
/// </summary>
bool IsSyncStructureToUpper { get; set; }
/// <summary>
/// 使用数据库的主键自增,适用 DbFirst 模式,无须在实体类型上设置 [Column(IsPrimary)] 或者 ConfigEntity。此功能目前可用于 mysql/sqlserver/postgresql
/// 数据库的主键自增、索引设置导入,适用 DbFirst 模式,无须在实体类型上设置 [Column(IsPrimary)] 或者 ConfigEntity。此功能目前可用于 mysql/sqlserver/postgresql/oracle。<para></para>
/// 本功能会影响 IFreeSql 首次访问的速度。<para></para>
/// 若使用 CodeFirst 创建索引后,又直接在数据库上建了索引,若无本功能下一次 CodeFirst 迁移时数据库上创建的索引将被删除
/// </summary>
bool IsConfigEntityFromDbFirst { get; set; }
/// <summary>

View File

@ -125,7 +125,6 @@ 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 (trycol._Uniques != null) attr._Uniques = trycol._Uniques;
if (trycol.MapType != null) attr.MapType = trycol.MapType;
if (trycol._Position != null) attr._Position = trycol.Position;
if (trycol._CanInsert != null) attr._CanInsert = trycol.CanInsert;
@ -145,7 +144,6 @@ 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 (tryattr._Uniques != null) attr._Uniques = tryattr._Uniques;
if (tryattr.MapType != null) attr.MapType = tryattr.MapType;
if (tryattr._Position != null) attr._Position = tryattr.Position;
if (tryattr._CanInsert != null) attr._CanInsert = tryattr.CanInsert;
@ -161,7 +159,6 @@ namespace FreeSql.Internal
if (attr._IsNullable != null) ret = attr;
if (attr._IsIgnore != null) ret = attr;
if (attr._IsVersion != null) ret = attr;
if (attr._Uniques != null) ret = attr;
if (attr.MapType != null) ret = attr;
if (attr._Position != null) ret = attr;
if (attr._CanInsert != null) ret = attr;
@ -191,6 +188,29 @@ namespace FreeSql.Internal
if (attr.ManyToMany != null) ret = attr;
return ret;
}
public IndexAttribute[] GetEntityIndexAttribute(Type type)
{
var ret = new Dictionary<string, IndexAttribute>(); ;
if (dicConfigEntity.TryGetValue(type, out var trytb))
{
foreach (var idxattr in trytb._indexs.Values)
{
if (!string.IsNullOrEmpty(idxattr.Name) && !string.IsNullOrEmpty(idxattr.Fields))
ret.Add(idxattr.Name, new IndexAttribute(idxattr.Name, idxattr.Fields) { _IsUnique = idxattr._IsUnique });
}
}
var attrs = type.GetCustomAttributes(typeof(IndexAttribute), true);
foreach (var tryattrobj in attrs)
{
var idxattr = tryattrobj as IndexAttribute;
if (idxattr == null) continue;
if (string.IsNullOrEmpty(idxattr.Name)) continue;
if (string.IsNullOrEmpty(idxattr.Fields)) continue;
if (ret.ContainsKey(idxattr.Name)) ret.Remove(idxattr.Name);
ret.Add(idxattr.Name, new IndexAttribute(idxattr.Name, idxattr.Fields) { _IsUnique = idxattr._IsUnique });
}
return ret.Values.ToArray();
}
public string WhereObject(TableInfo table, string aliasAndDot, object dywhere)
{

View File

@ -0,0 +1,21 @@
using FreeSql.DataAnnotations;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq.Expressions;
namespace FreeSql.Internal.Model
{
public class IndexInfo
{
public string Name { get; set; }
public IndexColumnInfo[] Columns { get; set; }
public bool IsUnique { get; set; }
}
public class IndexColumnInfo
{
public ColumnInfo Column { get; set; }
public bool IsDesc { get; set; }
}
}

View File

@ -1,4 +1,5 @@
using System;
using FreeSql.DataAnnotations;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Reflection;
@ -16,7 +17,7 @@ namespace FreeSql.Internal.Model
public Dictionary<string, ColumnInfo> ColumnsByCsIgnore { get; set; } = new Dictionary<string, ColumnInfo>(StringComparer.CurrentCultureIgnoreCase);
public ColumnInfo[] ColumnsByPosition { get; set; }
public ColumnInfo[] Primarys { get; set; }
public Dictionary<string, List<ColumnInfo>> Uniques { get; set; }
public IndexInfo[] Indexes { get; set; }
public string CsName { get; set; }
public string DbName { get; set; }
public string DbOldName { get; set; }

View File

@ -103,7 +103,6 @@ namespace FreeSql.Internal
IsNullable = tp.Value.isnullable ?? true,
IsPrimary = false,
IsIgnore = false,
Unique = null,
MapType = p.PropertyType
};
if (colattr._IsNullable == null) colattr._IsNullable = tp?.isnullable;
@ -119,16 +118,8 @@ namespace FreeSql.Internal
if (tp != null && tp.Value.isnullable == null) colattr.IsNullable = tp.Value.dbtypeFull.Contains("NOT NULL") == false;
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();
colattr.Unique = colattr.Unique?.ToLower();
}
if (common.CodeFirst.IsSyncStructureToUpper)
{
colattr.Name = colattr.Name.ToUpper();
colattr.Unique = colattr.Unique?.ToUpper();
}
if (common.CodeFirst.IsSyncStructureToLower) colattr.Name = colattr.Name.ToLower();
if (common.CodeFirst.IsSyncStructureToUpper) colattr.Name = colattr.Name.ToUpper();
if ((colattr.IsNullable != true || colattr.IsIdentity == true || colattr.IsPrimary == true) && colattr.DbType.Contains("NOT NULL") == false)
{
@ -183,27 +174,9 @@ namespace FreeSql.Internal
if (trytb.VersionColumn.Attribute.MapType.IsNullableType() || trytb.VersionColumn.Attribute.MapType.IsNumberType() == false)
throw new Exception($"属性{trytb.VersionColumn.CsName} 被标注为行锁(乐观锁)(IsVersion),但其必须为数字类型,并且不可为 Nullable");
}
trytb.Primarys = trytb.Columns.Values.Where(a => a.Attribute.IsPrimary == true).ToArray();
if (trytb.Primarys.Any() == false)
{
var identcol = trytb.Columns.Values.Where(a => a.Attribute.IsIdentity == true).FirstOrDefault();
if (identcol != null) trytb.Primarys = new[] { identcol };
if (trytb.Primarys.Any() == false)
{
trytb.Primarys = trytb.Columns.Values.Where(a => string.Compare(a.Attribute.Name, "id", true) == 0).ToArray();
if (trytb.Primarys.Any() == false)
{
trytb.Primarys = trytb.Columns.Values.Where(a => string.Compare(a.Attribute.Name, $"{trytb.DbName}id", true) == 0).ToArray();
if (trytb.Primarys.Any() == false)
{
trytb.Primarys = trytb.Columns.Values.Where(a => string.Compare(a.Attribute.Name, $"{trytb.DbName}_id", true) == 0).ToArray();
}
}
}
foreach (var col in trytb.Primarys)
col.Attribute.IsPrimary = true;
}
//从数据库查找主键、自增
var indexesDict = new Dictionary<string, IndexInfo>(StringComparer.CurrentCultureIgnoreCase);
//从数据库查找主键、自增、索引
if (common.CodeFirst.IsConfigEntityFromDbFirst)
{
try
@ -220,37 +193,99 @@ namespace FreeSql.Internal
{
foreach (var dbident in dbtb.Identitys)
{
if (trytb.Columns.TryGetValue(dbident.Name, out var trycol) && trycol.Attribute.MapType == dbident.CsType ||
trytb.ColumnsByCs.TryGetValue(dbident.Name, out trycol) && trycol.Attribute.MapType == dbident.CsType)
if (trytb.Columns.TryGetValue(dbident.Name, out var trycol) && trycol.Attribute.MapType.NullableTypeOrThis() == dbident.CsType.NullableTypeOrThis() ||
trytb.ColumnsByCs.TryGetValue(dbident.Name, out trycol) && trycol.Attribute.MapType.NullableTypeOrThis() == dbident.CsType.NullableTypeOrThis())
trycol.Attribute.IsIdentity = true;
}
foreach (var dbpk in dbtb.Primarys)
{
if (trytb.Columns.TryGetValue(dbpk.Name, out var trycol) && trycol.Attribute.MapType == dbpk.CsType ||
trytb.ColumnsByCs.TryGetValue(dbpk.Name, out trycol) && trycol.Attribute.MapType == dbpk.CsType)
if (trytb.Columns.TryGetValue(dbpk.Name, out var trycol) && trycol.Attribute.MapType.NullableTypeOrThis() == dbpk.CsType.NullableTypeOrThis() ||
trytb.ColumnsByCs.TryGetValue(dbpk.Name, out trycol) && trycol.Attribute.MapType.NullableTypeOrThis() == dbpk.CsType.NullableTypeOrThis())
trycol.Attribute.IsPrimary = true;
}
foreach (var dbuk in dbtb.UniquesDict)
foreach (var dbidx in dbtb.IndexesDict)
{
foreach (var dbcol in dbuk.Value)
var indexColumns = new List<IndexColumnInfo>();
foreach (var dbcol in dbidx.Value.Columns)
{
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)
if (trycol.Attribute._Uniques?.Contains(dbuk.Key) != true)
trycol.Attribute.Unique += $"," + dbuk.Key;
if (trytb.Columns.TryGetValue(dbcol.Column.Name, out var trycol) && trycol.Attribute.MapType.NullableTypeOrThis() == dbcol.Column.CsType.NullableTypeOrThis() ||
trytb.ColumnsByCs.TryGetValue(dbcol.Column.Name, out trycol) && trycol.Attribute.MapType.NullableTypeOrThis() == dbcol.Column.CsType.NullableTypeOrThis())
indexColumns.Add(new IndexColumnInfo
{
Column = trycol,
IsDesc = dbcol.IsDesc
});
}
if (indexColumns.Any() == false) continue;
if (indexesDict.ContainsKey(dbidx.Key)) indexesDict.Remove(dbidx.Key);
indexesDict.Add(dbidx.Key, new IndexInfo
{
Name = dbidx.Key,
Columns = indexColumns.ToArray(),
IsUnique = dbidx.Value.IsUnique
});
}
}
}
}
catch { }
trytb.Primarys = trytb.Columns.Values.Where(a => a.Attribute.IsPrimary == true).ToArray();
}
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());
//索引和唯一键
var indexes = common.GetEntityIndexAttribute(trytb.Type);
foreach (var index in indexes)
{
var val = index.Fields?.Trim(' ', '\t', ',');
if (string.IsNullOrEmpty(val)) continue;
var arr = val.Split(',').Select(a => a.Trim(' ', '\t').Trim()).Where(a => !string.IsNullOrEmpty(a)).ToArray();
if (arr.Any() == false) continue;
var indexColumns = new List<IndexColumnInfo>();
foreach (var field in arr)
{
var idxcol = new IndexColumnInfo();
if (field.EndsWith(" DESC", StringComparison.CurrentCultureIgnoreCase)) idxcol.IsDesc = true;
var colname = Regex.Replace(field, " (DESC|ASC)", "", RegexOptions.IgnoreCase);
if (trytb.ColumnsByCs.TryGetValue(colname, out var trycol) || trytb.Columns.TryGetValue(colname, out trycol))
{
idxcol.Column = trycol;
indexColumns.Add(idxcol);
}
}
if (indexColumns.Any() == false) continue;
var indexName = common.CodeFirst.IsSyncStructureToLower ? index.Name.ToLower() : (common.CodeFirst.IsSyncStructureToUpper ? index.Name.ToUpper() : index.Name);
if (indexesDict.ContainsKey(indexName)) indexesDict.Remove(indexName);
indexesDict.Add(indexName, new IndexInfo
{
Name = indexName,
Columns = indexColumns.ToArray(),
IsUnique = index.IsUnique
});
}
trytb.Indexes = indexesDict.Values.ToArray();
trytb.ColumnsByPosition = columnsList.Where(a => a.Attribute.Position > 0).OrderBy(a => a.Attribute.Position)
.Concat(columnsList.Where(a => a.Attribute.Position == 0))
.Concat(columnsList.Where(a => a.Attribute.Position < 0).OrderBy(a => a.Attribute.Position)).ToArray();
trytb.Primarys = trytb.Columns.Values.Where(a => a.Attribute.IsPrimary == true).ToArray();
if (trytb.Primarys.Any() == false)
{
trytb.Primarys = trytb.Columns.Values.Where(a => string.Compare(a.Attribute.Name, "id", true) == 0).ToArray();
if (trytb.Primarys.Any() == false)
{
var identcol = trytb.Columns.Values.Where(a => a.Attribute.IsIdentity == true).FirstOrDefault();
if (identcol != null) trytb.Primarys = new[] { identcol };
if (trytb.Primarys.Any() == false)
{
trytb.Primarys = trytb.Columns.Values.Where(a => string.Compare(a.Attribute.Name, $"{trytb.DbName}id", true) == 0).ToArray();
if (trytb.Primarys.Any() == false)
{
trytb.Primarys = trytb.Columns.Values.Where(a => string.Compare(a.Attribute.Name, $"{trytb.DbName}_id", true) == 0).ToArray();
}
}
}
foreach (var col in trytb.Primarys)
col.Attribute.IsPrimary = true;
}
foreach (var col in trytb.Primarys) col.Attribute.IsNullable = false;
tbc.AddOrUpdate(entity, trytb, (oldkey, oldval) => trytb);
#region virtual