- 修复 导航属性配置,循环关系的情况下可能导致的 bug;

This commit is contained in:
28810 2019-09-01 18:03:33 +08:00
parent ef18b61e84
commit 96796106d5

View File

@ -246,7 +246,6 @@ namespace FreeSql.Internal
#region virtual
var trytbTypeName = trytb.Type.IsNested ? $"{trytb.Type.DeclaringType.Namespace?.NotNullAndConcat(".")}{trytb.Type.DeclaringType.Name}.{trytb.Type.Name}" : $"{trytb.Type.Namespace?.NotNullAndConcat(".")}{trytb.Type.Name}";
var trytbTypeLazyName = default(string);
var overrieds = 0;
StringBuilder cscode = null;
if (common.CodeFirst.IsLazyLoading && propsLazy.Any())
{
@ -265,10 +264,39 @@ namespace FreeSql.Internal
.AppendLine(" [JsonIgnore] private IFreeSql __fsql_orm__ { get; set; }\r\n");
}
var cscodeLength = cscode?.Length ?? 0;
foreach (var pnv in propsNavObjs)
{
var vp = propsLazy.Where(a => a.Item1 == pnv).FirstOrDefault();
var isLazy = vp.Item1 != null && !string.IsNullOrEmpty(trytbTypeLazyName);
AddTableRef(common, trytb, pnv, isLazy, vp, cscode);
}
if (cscode?.Length > cscodeLength)
{
cscode.AppendLine("}");
Assembly assembly = null;
if (MethodLazyLoadingComplier.Value == null) throw new Exception("【延时加载】功能需要安装 FreeSql.Extensions.LazyLoading.dll可前往 nuget 下载");
try
{
assembly = MethodLazyLoadingComplier.Value.Invoke(null, new object[] { cscode.ToString() }) as Assembly;
}
catch (Exception ex)
{
throw new Exception($"【延时加载】{trytbTypeName} 编译错误:{ex.Message}\r\n\r\n{cscode}");
}
var type = assembly.DefinedTypes.Where(a => a.FullName.EndsWith(trytbTypeLazyName)).FirstOrDefault();
trytb.TypeLazy = type;
trytb.TypeLazySetOrm = type.GetProperty("__fsql_orm__", BindingFlags.Instance | BindingFlags.NonPublic).GetSetMethod(true);
tbc.AddOrUpdate(type, trytb, (oldkey, oldval) => trytb);
}
#endregion
return tbc.TryGetValue(entity, out var trytb2) ? trytb2 : trytb;
}
public static void AddTableRef(CommonUtils common, TableInfo trytb, PropertyInfo pnv, bool isLazy, (PropertyInfo, bool, bool)? vp, StringBuilder cscode)
{
var trytbTypeName = trytb.Type.IsNested ? $"{trytb.Type.DeclaringType.Namespace?.NotNullAndConcat(".")}{trytb.Type.DeclaringType.Name}.{trytb.Type.Name}" : $"{trytb.Type.Namespace?.NotNullAndConcat(".")}{trytb.Type.Name}";
var propTypeName = pnv.PropertyType.IsGenericType ?
$"{pnv.PropertyType.Namespace?.NotNullAndConcat(".")}{pnv.PropertyType.Name.Remove(pnv.PropertyType.Name.IndexOf('`'))}<{string.Join(", ", pnv.PropertyType.GenericTypeArguments.Select(a => a.IsNested ? $"{a.DeclaringType.Namespace?.NotNullAndConcat(".")}{a.DeclaringType.Name}.{a.Name}" : $"{a.Namespace?.NotNullAndConcat(".")}{a.Name}"))}>" :
(pnv.PropertyType.IsNested ? $"{pnv.PropertyType.DeclaringType.Namespace?.NotNullAndConcat(".")}{pnv.PropertyType.DeclaringType.Name}.{pnv.PropertyType.Name}" : $"{pnv.PropertyType.Namespace?.NotNullAndConcat(".")}{pnv.PropertyType.Name}");
@ -282,17 +310,17 @@ namespace FreeSql.Internal
var propElementType = pnv.PropertyType.GenericTypeArguments.FirstOrDefault() ?? pnv.PropertyType.GetElementType();
if (propElementType != null)
{
if (typeof(IEnumerable).IsAssignableFrom(pnv.PropertyType) == false) continue;
if (typeof(IEnumerable).IsAssignableFrom(pnv.PropertyType) == false) return;
if (trytb.Primarys.Any() == false)
{
nvref.Exception = new Exception($"导航属性 {trytbTypeName}.{pnv.Name} 解析错误,实体类型 {trytbTypeName} 缺少主键标识,[Column(IsPrimary = true)]");
trytb.AddOrUpdateTableRef(pnv.Name, nvref);
//if (isLazy) throw nvref.Exception;
continue;
return;
}
var tbref = propElementType == trytb.Type ? trytb : GetTableByEntity(propElementType, common); //可能是父子关系
if (tbref == null) continue;
if (tbref == null) return;
var tbrefTypeName = tbref.Type.IsNested ? $"{tbref.Type.DeclaringType.Namespace?.NotNullAndConcat(".")}{tbref.Type.DeclaringType.Name}.{tbref.Type.Name}" : $"{tbref.Type.Namespace?.NotNullAndConcat(".")}{tbref.Type.Name}";
Type midType = null;
@ -321,7 +349,7 @@ namespace FreeSql.Internal
nvref.Exception = new Exception($"【ManyToMany】导航属性 {trytbTypeName}.{pnv.Name} 解析错误,实体类型 {tbrefTypeName} 必须存在对应的 [Navigate(ManyToMany = x)] 集合属性");
trytb.AddOrUpdateTableRef(pnv.Name, nvref);
//if (isLazy) throw nvref.Exception;
continue;
return;
}
if (isManyToMany)
{
@ -344,7 +372,7 @@ namespace FreeSql.Internal
nvref.Exception = new Exception($"【ManyToMany】导航属性 {trytbTypeName}.{pnv.Name} 解析错误,实体类型 {tbrefTypeName} 缺少主键标识,[Column(IsPrimary = true)]");
trytb.AddOrUpdateTableRef(pnv.Name, nvref);
//if (isLazy) throw nvref.Exception;
continue;
return;
}
if (pnvAttr?.ManyToMany == null)
{
@ -432,6 +460,11 @@ namespace FreeSql.Internal
try
{
trytbTf = tbmid.GetTableRef(midTypePropsTrytb.Name, true);
if (trytbTf == null)
{
AddTableRef(common, tbmid, midTypePropsTrytb, false, null, null);
trytbTf = tbmid.GetTableRef(midTypePropsTrytb.Name, true);
}
}
catch (Exception ex)
{
@ -472,6 +505,11 @@ namespace FreeSql.Internal
try
{
tbrefTf = tbmid.GetTableRef(midTypePropsTbref.Name, true);
if (tbrefTf == null)
{
AddTableRef(common, tbmid, midTypePropsTbref, false, null, null);
tbrefTf = tbmid.GetTableRef(midTypePropsTbref.Name, true);
}
}
catch (Exception ex)
{
@ -598,7 +636,7 @@ namespace FreeSql.Internal
{
cscode.Append(" private bool __lazy__").Append(pnv.Name).AppendLine(" = false;")
.Append(" public override ").Append(propTypeName).Append(" ").Append(pnv.Name).AppendLine(" {");
if (vp.Item2)
if (vp?.Item2 == true)
{ //get 重写
cscode.Append(" get {\r\n")
.Append(" if (base.").Append(pnv.Name).Append(" == null && __lazy__").Append(pnv.Name).AppendLine(" == false) {");
@ -615,7 +653,7 @@ namespace FreeSql.Internal
.Append(" return base.").Append(pnv.Name).AppendLine(";")
.Append(" }\r\n");
}
if (vp.Item3)
if (vp?.Item3 == true)
{ //set 重写
cscode.Append(" set => base.").Append(pnv.Name).AppendLine(" = value;");
}
@ -731,7 +769,7 @@ namespace FreeSql.Internal
{
cscode.Append(" private bool __lazy__").Append(pnv.Name).AppendLine(" = false;")
.Append(" public override ").Append(propTypeName).Append(" ").Append(pnv.Name).AppendLine(" {");
if (vp.Item2)
if (vp?.Item2 == true)
{ //get 重写
cscode.Append(" get {\r\n")
.Append(" if (base.").Append(pnv.Name).Append(" == null && __lazy__").Append(pnv.Name).AppendLine(" == false) {");
@ -754,7 +792,7 @@ namespace FreeSql.Internal
.Append(" return base.").Append(pnv.Name).AppendLine(";")
.Append(" }\r\n");
}
if (vp.Item3)
if (vp?.Item3 == true)
{ //set 重写
cscode.Append(" set => base.").Append(pnv.Name).AppendLine(" = value;");
}
@ -765,7 +803,7 @@ namespace FreeSql.Internal
else
{ //一对一、多对一
var tbref = pnv.PropertyType == trytb.Type ? trytb : GetTableByEntity(pnv.PropertyType, common); //可能是父子关系
if (tbref == null) continue;
if (tbref == null) return;
if (tbref.Primarys.Any() == false)
{
nvref.Exception = new Exception($"导航属性 {trytbTypeName}.{pnv.Name} 解析错误,实体类型 {propTypeName} 缺少主键标识,[Column(IsPrimary = true)]");
@ -885,7 +923,7 @@ namespace FreeSql.Internal
{
cscode.Append(" private bool __lazy__").Append(pnv.Name).AppendLine(" = false;")
.Append(" public override ").Append(propTypeName).Append(" ").Append(pnv.Name).AppendLine(" {");
if (vp.Item2)
if (vp?.Item2 == true)
{ //get 重写
cscode.Append(" get {\r\n")
.Append(" if (base.").Append(pnv.Name).Append(" == null && __lazy__").Append(pnv.Name).AppendLine(" == false) {");
@ -901,7 +939,7 @@ namespace FreeSql.Internal
.Append(" return base.").Append(pnv.Name).AppendLine(";")
.Append(" }\r\n");
}
if (vp.Item3)
if (vp?.Item3 == true)
{ //set 重写
cscode.Append(" set {\r\n")
.Append(" base.").Append(pnv.Name).AppendLine(" = value;")
@ -911,30 +949,6 @@ namespace FreeSql.Internal
cscode.AppendLine(" }");
}
}
if (isLazy) ++overrieds;
}
if (overrieds > 0)
{
cscode.AppendLine("}");
Assembly assembly = null;
if (MethodLazyLoadingComplier.Value == null) throw new Exception("【延时加载】功能需要安装 FreeSql.Extensions.LazyLoading.dll可前往 nuget 下载");
try
{
assembly = MethodLazyLoadingComplier.Value.Invoke(null, new object[] { cscode.ToString() }) as Assembly;
}
catch (Exception ex)
{
throw new Exception($"【延时加载】{trytbTypeName} 编译错误:{ex.Message}\r\n\r\n{cscode}");
}
var type = assembly.DefinedTypes.Where(a => a.FullName.EndsWith(trytbTypeLazyName)).FirstOrDefault();
trytb.TypeLazy = type;
trytb.TypeLazySetOrm = type.GetProperty("__fsql_orm__", BindingFlags.Instance | BindingFlags.NonPublic).GetSetMethod(true);
tbc.AddOrUpdate(type, trytb, (oldkey, oldval) => trytb);
}
#endregion
return tbc.TryGetValue(entity, out var trytb2) ? trytb2 : trytb;
}
static Lazy<MethodInfo> MethodLazyLoadingComplier = new Lazy<MethodInfo>(() =>
{