mirror of
https://github.com/nsnail/FreeSql.git
synced 2025-04-22 18:52:50 +08:00
virtual lazy 加载现实 OneToOne/ManyToOne/OneToMany
This commit is contained in:
parent
08b1df5d3f
commit
9ec287535e
@ -5,6 +5,7 @@ using System.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace FreeSql.Tests.MySql {
|
||||
|
||||
public class MySqlSelectTest {
|
||||
|
||||
ISelect<Topic> select => g.mysql.Select<Topic>();
|
||||
@ -15,18 +16,33 @@ namespace FreeSql.Tests.MySql {
|
||||
public int Id { get; set; }
|
||||
public int Clicks { get; set; }
|
||||
public int TestTypeInfoGuid { get; set; }
|
||||
public virtual TestTypeInfo TestTypeInfo { get; set; }
|
||||
|
||||
public int TypeGuid { get; set; }
|
||||
public virtual TestTypeInfo Type { get; set; }
|
||||
public string Title { get; set; }
|
||||
public DateTime CreateTime { get; set; }
|
||||
|
||||
public virtual TopicFields Fields { get; set; }
|
||||
}
|
||||
public class TopicFields {
|
||||
[Column(IsPrimary = true)]
|
||||
public int TopicId { get; set; }
|
||||
public virtual Topic Topic { get; set; }
|
||||
}
|
||||
public class TestTypeInfo {
|
||||
[Column(IsIdentity = true)]
|
||||
public int Guid { get; set; }
|
||||
|
||||
public int ParentId { get; set; }
|
||||
public TestTypeParentInfo Parent { get; set; }
|
||||
public virtual TestTypeParentInfo Parent { get; set; }
|
||||
|
||||
public int SelfGuid { get; set; }
|
||||
public virtual TestTypeInfo Self { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public virtual ICollection<Topic> Topics { get; set; }
|
||||
}
|
||||
public class TestTypeParentInfo {
|
||||
[Column(IsIdentity = true)]
|
||||
@ -38,6 +54,9 @@ namespace FreeSql.Tests.MySql {
|
||||
|
||||
[Fact]
|
||||
public void Lazy() {
|
||||
var ts = g.mysql.Select<TestTypeInfo>(1).ToOne();
|
||||
|
||||
|
||||
Topic t = g.mysql.Select<Topic>(2).ToOne();
|
||||
Topic tz = g.mysql.Select<Topic>(2).ToOne();
|
||||
var tzType = tz.Type;
|
||||
|
@ -26,11 +26,12 @@ namespace FreeSql.Internal {
|
||||
static ConcurrentDictionary<string, ConcurrentDictionary<Type, TableInfo>> _cacheGetTableByEntity = new ConcurrentDictionary<string, ConcurrentDictionary<Type, TableInfo>>();
|
||||
internal static TableInfo GetTableByEntity(Type entity, CommonUtils common) {
|
||||
if (entity.FullName.StartsWith("<>f__AnonymousType")) return null;
|
||||
return _cacheGetTableByEntity.GetOrAdd(common.DbName, k1 => new ConcurrentDictionary<Type, TableInfo>()).GetOrAdd(entity, k2 => { //区分数据库类型缓存
|
||||
var tbc = _cacheGetTableByEntity.GetOrAdd(common.DbName, k1 => new ConcurrentDictionary<Type, TableInfo>()); //区分数据库类型缓存
|
||||
if (tbc.TryGetValue(entity, out var trytb)) return trytb;
|
||||
if (common.CodeFirst.GetDbInfo(entity) != null) return null;
|
||||
|
||||
var tbattr = entity.GetCustomAttributes(typeof(TableAttribute), false).LastOrDefault() as TableAttribute;
|
||||
var trytb = new TableInfo();
|
||||
trytb = new TableInfo();
|
||||
trytb.Type = entity;
|
||||
trytb.Properties = entity.GetProperties().ToDictionary(a => a.Name, a => a, StringComparer.CurrentCultureIgnoreCase);
|
||||
trytb.CsName = entity.Name;
|
||||
@ -41,7 +42,7 @@ namespace FreeSql.Internal {
|
||||
trytb.DbOldName = trytb.DbOldName?.ToLower();
|
||||
}
|
||||
trytb.SelectFilter = tbattr?.SelectFilter;
|
||||
var virtualProps = new List<(PropertyInfo, bool, bool)>();
|
||||
var propsLazy = new List<(PropertyInfo, bool, bool)>();
|
||||
foreach (var p in trytb.Properties.Values) {
|
||||
var tp = common.CodeFirst.GetDbInfo(p.PropertyType);
|
||||
//if (tp == null) continue;
|
||||
@ -51,7 +52,7 @@ namespace FreeSql.Internal {
|
||||
var getIsVirtual = trytb.Type.GetMethod($"get_{p.Name}")?.IsVirtual;
|
||||
var setIsVirtual = trytb.Type.GetMethod($"set_{p.Name}")?.IsVirtual;
|
||||
if (getIsVirtual == true || setIsVirtual == true)
|
||||
virtualProps.Add((p, getIsVirtual == true, setIsVirtual == true));
|
||||
propsLazy.Add((p, getIsVirtual == true, setIsVirtual == true));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@ -88,6 +89,11 @@ namespace FreeSql.Internal {
|
||||
var consturctorType = p.PropertyType.GenericTypeArguments.FirstOrDefault() ?? p.PropertyType;
|
||||
colattr.DbDefautValue = Activator.CreateInstance(consturctorType);
|
||||
}
|
||||
if (colattr.IsIdentity && new[] {
|
||||
typeof(sbyte), typeof(short), typeof(int), typeof(long),
|
||||
typeof(byte), typeof(ushort), typeof(uint), typeof(ulong),
|
||||
typeof(double), typeof(float), typeof(decimal) }.Contains(p.PropertyType.GenericTypeArguments.FirstOrDefault() ?? p.PropertyType) == false)
|
||||
colattr.IsIdentity = false;
|
||||
|
||||
var col = new ColumnInfo {
|
||||
Table = trytb,
|
||||
@ -104,11 +110,14 @@ namespace FreeSql.Internal {
|
||||
foreach (var col in trytb.Primarys)
|
||||
col.Attribute.IsPrimary = true;
|
||||
}
|
||||
tbc.TryAdd(entity, trytb);
|
||||
|
||||
if (common.CodeFirst.IsLazyLoading && virtualProps.Any()) {
|
||||
//virtual 属性延时加载,生态产生新的重写类
|
||||
if (trytb.Type.IsNestedPublic == false) throw new Exception("【延时加载】功能发生错误,实体类必须声明为 public");
|
||||
//virtual 属性延时加载,动态产生新的重写类
|
||||
if (common.CodeFirst.IsLazyLoading && propsLazy.Any()) {
|
||||
var trytbTypeName = trytb.Type.IsNested ? $"{trytb.Type.DeclaringType.Namespace}.{trytb.Type.DeclaringType.Name}.{trytb.Type.Name}" : $"{trytb.Type.Namespace}.{trytb.Type.Name}";
|
||||
if (trytb.Type.IsPublic == false && trytb.Type.IsNestedPublic == false) throw new Exception($"【延时加载】实体类型 {trytbTypeName} 必须声明为 public");
|
||||
|
||||
var trytbTypeLazyName = $"FreeSqlLazyEntity__{Regex.Replace(trytbTypeName, @"[^\w\d]", "_")}";
|
||||
var overrieds = 0;
|
||||
var cscode = new StringBuilder();
|
||||
cscode.AppendLine("using System;")
|
||||
@ -116,56 +125,164 @@ namespace FreeSql.Internal {
|
||||
.AppendLine("using System.Collections.Generic;")
|
||||
.AppendLine("using System.Linq;")
|
||||
.AppendLine("")
|
||||
.Append("public class FreeSqlOverrideLazyEntity").Append(trytb.Type.Name).Append(" : ").Append(trytb.Type.FullName.Replace("+", ".")).AppendLine(" {")
|
||||
.Append("public class ").Append(trytbTypeLazyName).Append(" : ").Append(trytbTypeName).AppendLine(" {")
|
||||
.AppendLine(" public IFreeSql __fsql_orm__ { get; set; }\r\n");
|
||||
foreach(var vp in virtualProps) {
|
||||
TableInfo pktb = null;
|
||||
if (vp.Item1.PropertyType == trytb.Type) pktb = trytb;
|
||||
else pktb = GetTableByEntity(vp.Item1.PropertyType, common);
|
||||
if (pktb == null || pktb.Primarys.Any() == false) {
|
||||
//continue;
|
||||
throw new Exception($"【延时加载】功能发生错误,导航属性 {trytb.Type.FullName}.{vp.Item1.Name} 类型不正确,或者实体类型 {vp.Item1.PropertyType.FullName} 缺少主键标识");
|
||||
}
|
||||
|
||||
foreach (var vp in propsLazy) {
|
||||
var propTypeName = vp.Item1.PropertyType.IsGenericType ?
|
||||
$"{vp.Item1.PropertyType.Namespace}.{vp.Item1.PropertyType.Name.Remove(vp.Item1.PropertyType.Name.IndexOf('`'))}<{string.Join(", ", vp.Item1.PropertyType.GenericTypeArguments.Select(a => a.IsNested ? $"{a.DeclaringType.Namespace}.{a.DeclaringType.Name}.{a.Name}" : $"{a.Namespace}.{a.Name}"))}>" :
|
||||
(vp.Item1.PropertyType.IsNested ? $"{vp.Item1.PropertyType.DeclaringType.Namespace}.{vp.Item1.PropertyType.DeclaringType.Name}.{vp.Item1.PropertyType.Name}" : $"{vp.Item1.PropertyType.Namespace}.{vp.Item1.PropertyType.Name}");
|
||||
//List 或 ICollection,一对多、多对多
|
||||
var propElementType = vp.Item1.PropertyType.GenericTypeArguments.FirstOrDefault() ?? vp.Item1.PropertyType.GetElementType();
|
||||
if (propElementType != null) {
|
||||
if (Activator.CreateInstance(vp.Item1.PropertyType) is ICollection == false) continue;
|
||||
|
||||
if (trytb.Primarys.Any() == false) {
|
||||
//continue;
|
||||
throw new Exception($"【延时加载】导航属性 {vp.Item1.Name} 解析错误,实体类型 {trytbTypeName} 缺少主键标识,[Column(IsPrimary = true)]");
|
||||
}
|
||||
var tbref = propElementType == trytb.Type ? trytb : GetTableByEntity(propElementType, common); //可能是父子关系
|
||||
if (tbref == null) continue;
|
||||
|
||||
var isManyToMany = propElementType != trytb.Type &&
|
||||
tbref.Properties.Where(z => (z.Value.PropertyType.GenericTypeArguments.FirstOrDefault() == trytb.Type || z.Value.PropertyType.GetElementType() == trytb.Type) &&
|
||||
vp.Item1.Name.EndsWith($"{z.Key}s", StringComparison.CurrentCultureIgnoreCase) &&
|
||||
z.Key.EndsWith($"{trytb.CsName}s", StringComparison.CurrentCultureIgnoreCase) &&
|
||||
Activator.CreateInstance(z.Value.PropertyType) is ICollection).Any();
|
||||
//中间表怎么查询
|
||||
if (isManyToMany) continue;
|
||||
|
||||
var refcols = tbref.Properties.Where(z => z.Value.PropertyType == trytb.Type);
|
||||
var refprop = refcols.Count() == 1 ? refcols.First().Value : null;
|
||||
var lmbdWhere = new StringBuilder();
|
||||
var vpcols = new ColumnInfo[pktb.Primarys.Length];
|
||||
for (var a = 0; a < pktb.Primarys.Length; a++) {
|
||||
if (trytb.ColumnsByCs.TryGetValue($"{vp.Item1.Name}{pktb.Primarys[a].CsName}", out var trycol) == false && //骆峰命名
|
||||
trytb.ColumnsByCs.TryGetValue($"{vp.Item1.Name}_{pktb.Primarys[a].CsName}", out trycol) == false //下划线命名
|
||||
var vpcols = new ColumnInfo[trytb.Primarys.Length];
|
||||
for (var a = 0; a < trytb.Primarys.Length; a++) {
|
||||
var findtrytbPkCsName = trytb.Primarys[a].CsName.TrimStart('_');
|
||||
if (findtrytbPkCsName.StartsWith(trytb.Type.Name, StringComparison.CurrentCultureIgnoreCase)) findtrytbPkCsName = findtrytbPkCsName.Substring(trytb.Type.Name.Length).TrimStart('_');
|
||||
var findtrytb = vp.Item1.Name;
|
||||
if (findtrytb.EndsWith(tbref.CsName + "s")) findtrytb = findtrytb.Substring(0, findtrytb.Length - tbref.CsName.Length - 1);
|
||||
findtrytb += trytb.CsName;
|
||||
if (tbref.ColumnsByCs.TryGetValue($"{findtrytb}{findtrytbPkCsName}", out var trycol) == false && //骆峰命名
|
||||
tbref.ColumnsByCs.TryGetValue($"{findtrytb}_{findtrytbPkCsName}", out trycol) == false //下划线命名
|
||||
) {
|
||||
pktb = null;
|
||||
throw new Exception($"【延时加载】功能发生错误,导航属性 {trytb.Type.FullName}.{vp.Item1.Name} 没有找到对应的字段 {vp.Item1.Name}{pktb.Primarys[a].CsName} 或 {vp.Item1.Name}_{pktb.Primarys[a].CsName}");
|
||||
//break;
|
||||
if (refprop != null &&
|
||||
tbref.ColumnsByCs.TryGetValue($"{refprop.Name}{findtrytbPkCsName}", out trycol) == false && //骆峰命名
|
||||
tbref.ColumnsByCs.TryGetValue($"{refprop.Name}_{findtrytbPkCsName}", out trycol) == false) //下划线命名
|
||||
{
|
||||
|
||||
}
|
||||
if (trycol != null && trycol.CsType != tbref.Primarys[a].CsType)
|
||||
throw new Exception($"【延时加载】导航属性 {trytbTypeName}.{vp.Item1.Name} 解析错误,{trytb.CsName}.{trytb.Primarys[a].CsName} 和 {tbref.CsName}.{trycol.CsName} 类型不一致");
|
||||
if (trycol == null)
|
||||
throw new Exception($"【延时加载】导航属性 {trytbTypeName}.{vp.Item1.Name} 在 {tbref.CsName} 中没有找到对应的字段,如:{findtrytb}{findtrytbPkCsName}、{findtrytb}_{findtrytbPkCsName}、{refprop.Name}{findtrytbPkCsName}、{refprop.Name}_{findtrytbPkCsName}");
|
||||
}
|
||||
if (a > 0) lmbdWhere.Append(" && ");
|
||||
lmbdWhere.Append("a.").Append(pktb.Primarys[a].CsName).Append(" == this.").Append(trycol.CsName);
|
||||
}
|
||||
if (pktb == null) continue;
|
||||
lmbdWhere.Append("a.").Append(trycol.CsName).Append(" == this.").Append(trytb.Primarys[a].CsName);
|
||||
|
||||
cscode.Append(" public override ").Append(vp.Item1.PropertyType.FullName.Replace("+", ".")).Append(" ").Append(vp.Item1.Name).AppendLine(" {");
|
||||
if (refprop == null) {
|
||||
var findtrytbName = trycol.CsName;
|
||||
if (findtrytbName.EndsWith(trytb.Primarys.First().CsName)) {
|
||||
findtrytbName = findtrytbName.Remove(findtrytbName.Length - trytb.Primarys.First().CsName.Length).TrimEnd('_');
|
||||
if (tbref.Properties.TryGetValue(findtrytbName, out refprop) && refprop.PropertyType != trytb.Type)
|
||||
refprop = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cscode.Append(" private bool __lazy__").Append(vp.Item1.Name).AppendLine(" = false;")
|
||||
.Append(" public override ").Append(propTypeName).Append(" ").Append(vp.Item1.Name).AppendLine(" {");
|
||||
if (vp.Item2) { //get 重写
|
||||
cscode.Append(" get => base.").Append(vp.Item1.Name)
|
||||
.Append(" ?? (base.").Append(vp.Item1.Name)
|
||||
.Append(" = __fsql_orm__.Select<").Append(vp.Item1.PropertyType.FullName.Replace("+", ".")).Append(">().Where(a => ")
|
||||
.Append(lmbdWhere.ToString())
|
||||
.Append(").ToOne()").AppendLine(");");
|
||||
cscode.Append(" get {\r\n")
|
||||
.Append(" if (base.").Append(vp.Item1.Name).Append(" == null && __lazy__").Append(vp.Item1.Name).AppendLine(" == false) {")
|
||||
.Append(" base.").Append(vp.Item1.Name).Append(" = __fsql_orm__.Select<").Append(propElementType.IsNested ? $"{propElementType.DeclaringType.Namespace}.{propElementType.DeclaringType.Name}.{propElementType.Name}" : $"{propElementType.Namespace}.{propElementType.Name}").Append(">().Where(a => ").Append(lmbdWhere.ToString()).AppendLine(").ToList();");
|
||||
if (refprop != null) {
|
||||
cscode.Append(" foreach (var loc1 in base.").Append(vp.Item1.Name).AppendLine(")")
|
||||
.Append(" loc1.").Append(refprop.Name).AppendLine(" = this;");
|
||||
}
|
||||
cscode.Append(" __lazy__").Append(vp.Item1.Name).AppendLine(" = true;")
|
||||
.Append(" }\r\n")
|
||||
.Append(" return base.").Append(vp.Item1.Name).AppendLine(";")
|
||||
.Append(" }\r\n");
|
||||
}
|
||||
if (vp.Item3) { //set 重写
|
||||
cscode.Append(" set => base.").Append(vp.Item1.Name).AppendLine(" = value;");
|
||||
}
|
||||
cscode.AppendLine(" }");
|
||||
|
||||
} else { //一对一、多对一
|
||||
var tbref = vp.Item1.PropertyType == trytb.Type ? trytb : GetTableByEntity(vp.Item1.PropertyType, common); //可能是父子关系
|
||||
if (tbref == null) continue;
|
||||
if (tbref.Primarys.Any() == false) {
|
||||
//continue;
|
||||
throw new Exception($"【延时加载】导航属性 {trytbTypeName}.{vp.Item1.Name} 解析错误,实体类型 {propTypeName} 缺少主键标识,[Column(IsPrimary = true)]");
|
||||
}
|
||||
var isOnoToOne = vp.Item1.PropertyType != trytb.Type &&
|
||||
tbref.Properties.Where(z => z.Value.PropertyType == trytb.Type).Any() &&
|
||||
tbref.Primarys.Length == trytb.Primarys.Length &&
|
||||
string.Join(",", tbref.Primarys.Select(a => a.CsType.FullName)) == string.Join(",", trytb.Primarys.Select(a => a.CsType.FullName));
|
||||
var lmbdWhere = new StringBuilder();
|
||||
var vpcols = new ColumnInfo[tbref.Primarys.Length];
|
||||
for (var a = 0; a < tbref.Primarys.Length; a++) {
|
||||
var findtbrefPkCsName = tbref.Primarys[a].CsName.TrimStart('_');
|
||||
if (findtbrefPkCsName.StartsWith(tbref.Type.Name, StringComparison.CurrentCultureIgnoreCase)) findtbrefPkCsName = findtbrefPkCsName.Substring(tbref.Type.Name.Length).TrimStart('_');
|
||||
if (trytb.ColumnsByCs.TryGetValue($"{vp.Item1.Name}{findtbrefPkCsName}", out var trycol) == false && //骆峰命名
|
||||
trytb.ColumnsByCs.TryGetValue($"{vp.Item1.Name}_{findtbrefPkCsName}", out trycol) == false //下划线命名
|
||||
) {
|
||||
//一对一,主键与主键查找
|
||||
if (isOnoToOne) {
|
||||
var trytbpks = trytb.Primarys.Where(z => z.CsType == tbref.Primarys[a].CsType); //一对一,按类型
|
||||
if (trytbpks.Count() == 1) trycol = trytbpks.First();
|
||||
else {
|
||||
trytbpks = trytb.Primarys.Where(z => string.Compare(z.CsName, tbref.Primarys[a].CsName, true) == 0); //一对一,按主键名相同
|
||||
if (trytbpks.Count() == 1) trycol = trytbpks.First();
|
||||
else {
|
||||
trytbpks = trytb.Primarys.Where(z => string.Compare(z.CsName, $"{tbref.CsName}{tbref.Primarys[a].CsName}", true) == 0); //一对一,主键名 = 表+主键名
|
||||
if (trytbpks.Count() == 1) trycol = trytbpks.First();
|
||||
else {
|
||||
trytbpks = trytb.Primarys.Where(z => string.Compare(z.CsName, $"{tbref.CsName}_{tbref.Primarys[a].CsName}", true) == 0); //一对一,主键名 = 表+_主键名
|
||||
if (trytbpks.Count() == 1) trycol = trytbpks.First();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (trycol != null && trycol.CsType != tbref.Primarys[a].CsType)
|
||||
throw new Exception($"【延时加载】导航属性 {trytbTypeName}.{vp.Item1.Name} 解析错误,{trytb.CsName}.{trycol.CsName} 和 {tbref.CsName}.{tbref.Primarys[a].CsName} 类型不一致");
|
||||
if (trycol == null)
|
||||
throw new Exception($"【延时加载】导航属性 {trytbTypeName}.{vp.Item1.Name} 没有找到对应的字段,如:{vp.Item1.Name}{findtbrefPkCsName}、{vp.Item1.Name}_{findtbrefPkCsName}");
|
||||
}
|
||||
if (a > 0) lmbdWhere.Append(" && ");
|
||||
lmbdWhere.Append("a.").Append(tbref.Primarys[a].CsName).Append(" == this.").Append(trycol.CsName);
|
||||
}
|
||||
|
||||
cscode.Append(" private bool __lazy__").Append(vp.Item1.Name).AppendLine(" = false;")
|
||||
.Append(" public override ").Append(propTypeName).Append(" ").Append(vp.Item1.Name).AppendLine(" {");
|
||||
if (vp.Item2) { //get 重写
|
||||
cscode.Append(" get {\r\n")
|
||||
.Append(" if (base.").Append(vp.Item1.Name).Append(" == null && __lazy__").Append(vp.Item1.Name).AppendLine(" == false) {")
|
||||
.Append(" base.").Append(vp.Item1.Name).Append(" = __fsql_orm__.Select<").Append(propTypeName).Append(">().Where(a => ").Append(lmbdWhere.ToString()).AppendLine(").ToOne();")
|
||||
.Append(" __lazy__").Append(vp.Item1.Name).AppendLine(" = true;")
|
||||
.Append(" }\r\n")
|
||||
.Append(" return base.").Append(vp.Item1.Name).AppendLine(";")
|
||||
.Append(" }\r\n");
|
||||
}
|
||||
if (vp.Item3) { //set 重写
|
||||
cscode.Append(" set => base.").Append(vp.Item1.Name).AppendLine(" = value;");
|
||||
}
|
||||
cscode.AppendLine(" }");
|
||||
|
||||
}
|
||||
++overrieds;
|
||||
}
|
||||
if (overrieds > 0) {
|
||||
cscode.AppendLine("}");
|
||||
var assemly = Generator.TemplateEngin._compiler.Value.CompileCode(cscode.ToString());
|
||||
var type = assemly.DefinedTypes.Where(a => a.FullName.EndsWith($"FreeSqlOverrideLazyEntity{trytb.Type.Name}")).FirstOrDefault();
|
||||
var type = assemly.DefinedTypes.Where(a => a.FullName.EndsWith(trytbTypeLazyName)).FirstOrDefault();
|
||||
trytb.TypeLazy = type;
|
||||
trytb.TypeLazySetOrm = type.GetProperty("__fsql_orm__").GetSetMethod();
|
||||
}
|
||||
}
|
||||
return trytb;
|
||||
});
|
||||
|
||||
return tbc.TryGetValue(entity, out var trytb2) ? trytb2 : trytb;
|
||||
}
|
||||
|
||||
internal static T[] GetDbParamtersByObject<T>(string sql, object obj, string paramPrefix, Func<string, Type, object, T> constructorParamter) {
|
||||
|
@ -168,7 +168,9 @@ where a.table_schema in ({0}) and a.table_name in ({1})".FormatMySql(tboldname ?
|
||||
}, StringComparer.CurrentCultureIgnoreCase);
|
||||
|
||||
if (istmpatler == false) {
|
||||
var existsPrimary = ExecuteScalar(tbname[0], "select 1 from INFORMATION_SCHEMA.KEY_COLUMN_USAGE where table_schema={0} and table_name={1} limit 1".FormatMySql(tbname));
|
||||
foreach (var tbcol in tb.Columns.Values) {
|
||||
var isIdentityChanged = tbcol.Attribute.IsIdentity && tbcol.Attribute.DbType.IndexOf("AUTO_INCREMENT", StringComparison.CurrentCultureIgnoreCase) == -1;
|
||||
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.IndexOf(" unsigned", StringComparison.CurrentCultureIgnoreCase) != -1) != tbstructcol.is_unsigned ||
|
||||
@ -176,20 +178,20 @@ where a.table_schema in ({0}) and a.table_name in ({1})".FormatMySql(tboldname ?
|
||||
tbcol.Attribute.IsNullable != tbstructcol.is_nullable ||
|
||||
tbcol.Attribute.IsIdentity != tbstructcol.is_identity) {
|
||||
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" MODIFY ").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" ").Append(tbcol.Attribute.DbType);
|
||||
if (tbcol.Attribute.IsIdentity && tbcol.Attribute.DbType.IndexOf("AUTO_INCREMENT", StringComparison.CurrentCultureIgnoreCase) == -1) sbalter.Append(" AUTO_INCREMENT");
|
||||
if (isIdentityChanged) sbalter.Append(" AUTO_INCREMENT").Append(existsPrimary == null ? "" : ", DROP PRIMARY KEY").Append(", ADD PRIMARY KEY(").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(")");
|
||||
sbalter.Append(";\r\n");
|
||||
}
|
||||
if (tbstructcol.column == tbcol.Attribute.OldName) {
|
||||
//修改列名
|
||||
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" CHANGE COLUMN ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.OldName)).Append(" ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType);
|
||||
if (tbcol.Attribute.IsIdentity && tbcol.Attribute.DbType.IndexOf("AUTO_INCREMENT", StringComparison.CurrentCultureIgnoreCase) == -1) sb.Append(" AUTO_INCREMENT");
|
||||
if (isIdentityChanged) sb.Append(" AUTO_INCREMENT").Append(existsPrimary == null ? "" : ", DROP PRIMARY KEY").Append(", ADD PRIMARY KEY(").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(")");
|
||||
sbalter.Append(";\r\n");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
//添加列
|
||||
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ADD ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType);
|
||||
if (tbcol.Attribute.IsIdentity && tbcol.Attribute.DbType.IndexOf("AUTO_INCREMENT", StringComparison.CurrentCultureIgnoreCase) == -1) sbalter.Append(" AUTO_INCREMENT");
|
||||
if (isIdentityChanged) sbalter.Append(" AUTO_INCREMENT").Append(existsPrimary == null ? "" : ", DROP PRIMARY KEY").Append(", ADD PRIMARY KEY(").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(")");
|
||||
sbalter.Append(";\r\n");
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user