mirror of
https://github.com/nsnail/FreeSql.git
synced 2025-06-19 12:28:15 +08:00
- 增加 IndexAttribute 特性,自动迁移索引,以及对应的 FluentApi 方法;
- 移除 ColumnAttribute.Unique 属性设置,改为 IndexAttribute 特性设置唯一键;
This commit is contained in:
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
21
FreeSql/DatabaseModel/DbIndexInfo.cs
Normal file
21
FreeSql/DatabaseModel/DbIndexInfo.cs
Normal 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; }
|
||||
}
|
||||
}
|
@ -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">
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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)
|
||||
{
|
||||
|
21
FreeSql/Internal/Model/IndexInfo.cs
Normal file
21
FreeSql/Internal/Model/IndexInfo.cs
Normal 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; }
|
||||
}
|
||||
}
|
@ -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; }
|
||||
|
@ -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 属性延时加载,动态产生新的重写类
|
||||
|
Reference in New Issue
Block a user