diff --git a/FreeSql.DbContext/DbSet/DbSetAsync.cs b/FreeSql.DbContext/DbSet/DbSetAsync.cs index 13533430..5bdccd0c 100644 --- a/FreeSql.DbContext/DbSet/DbSetAsync.cs +++ b/FreeSql.DbContext/DbSet/DbSetAsync.cs @@ -155,8 +155,9 @@ namespace FreeSql if (tref == null) return; switch (tref.RefType) { - case Internal.Model.TableRefType.OneToOne: - case Internal.Model.TableRefType.ManyToOne: + case TableRefType.OneToOne: + case TableRefType.ManyToOne: + case TableRefType.ArrayToMany: throw new ArgumentException(DbContextStrings.PropertyOfType_IsNot_OneToManyOrManyToMany(_table.Type.FullName, propertyName)); } @@ -166,7 +167,7 @@ namespace FreeSql try { await AddOrUpdateNavigateAsync(item, false, propertyName, cancellationToken); - if (tref.RefType == Internal.Model.TableRefType.OneToMany) + if (tref.RefType == TableRefType.OneToMany) { await DbContextFlushCommandAsync(cancellationToken); //删除没有保存的数据,求出主体的条件 @@ -213,7 +214,7 @@ namespace FreeSql DbSet refSet = null; switch (tref.RefType) { - case Internal.Model.TableRefType.OneToOne: + case TableRefType.OneToOne: refSet = GetDbSetObject(tref.RefEntityType); var propValItem = GetItemValue(item, prop); if (propValItem == null) return; @@ -225,7 +226,8 @@ namespace FreeSql if (isAdd) await refSet.AddAsync(propValItem); else await refSet.AddOrUpdateAsync(propValItem); return; - case Internal.Model.TableRefType.ManyToOne: + case TableRefType.ManyToOne: + case TableRefType.ArrayToMany: return; } @@ -234,7 +236,7 @@ namespace FreeSql refSet = GetDbSetObject(tref.RefEntityType); switch (tref.RefType) { - case Internal.Model.TableRefType.ManyToMany: + case TableRefType.ManyToMany: var curList = new List(); foreach (var propValItem in propValEach) { @@ -327,7 +329,7 @@ namespace FreeSql await midSet.AddRangeAsync(midListAdd, cancellationToken); } break; - case Internal.Model.TableRefType.OneToMany: + case TableRefType.OneToMany: var addList = new List(); var addOrUpdateList = new List(); foreach (var propValItem in propValEach) diff --git a/FreeSql.DbContext/DbSet/DbSetSync.cs b/FreeSql.DbContext/DbSet/DbSetSync.cs index 8bafd8ad..fc9bb1e1 100644 --- a/FreeSql.DbContext/DbSet/DbSetSync.cs +++ b/FreeSql.DbContext/DbSet/DbSetSync.cs @@ -166,8 +166,9 @@ namespace FreeSql if (tref == null) return; switch (tref.RefType) { - case Internal.Model.TableRefType.OneToOne: - case Internal.Model.TableRefType.ManyToOne: + case TableRefType.OneToOne: + case TableRefType.ManyToOne: + case TableRefType.ArrayToMany: throw new ArgumentException(DbContextStrings.PropertyOfType_IsNot_OneToManyOrManyToMany(_table.Type.FullName, propertyName)); } @@ -177,7 +178,7 @@ namespace FreeSql try { AddOrUpdateNavigate(item, false, propertyName); - if (tref.RefType == Internal.Model.TableRefType.OneToMany) + if (tref.RefType == TableRefType.OneToMany) { DbContextFlushCommand(); //删除没有保存的数据,求出主体的条件 @@ -224,7 +225,7 @@ namespace FreeSql DbSet refSet = null; switch (tref.RefType) { - case Internal.Model.TableRefType.OneToOne: + case TableRefType.OneToOne: refSet = GetDbSetObject(tref.RefEntityType); var propValItem = GetItemValue(item, prop); if (propValItem == null) return; @@ -236,7 +237,8 @@ namespace FreeSql if (isAdd) refSet.Add(propValItem); else refSet.AddOrUpdate(propValItem); return; - case Internal.Model.TableRefType.ManyToOne: + case TableRefType.ManyToOne: + case TableRefType.ArrayToMany: return; } @@ -714,7 +716,7 @@ namespace FreeSql { return tb.Properties.Where(a => tb.ColumnsByCs.ContainsKey(a.Key) == false) .Select(a => new NativeTuple(tb.GetTableRef(a.Key, false), a.Value)) - .Where(a => a.Item1 != null && a.Item1.RefType != TableRefType.ManyToOne) + .Where(a => a.Item1 != null && new[] { TableRefType.OneToOne, TableRefType.OneToMany, TableRefType.ManyToMany }.Contains(a.Item1.RefType)) .ToList(); } void LocalEach(DbSet dbset, IEnumerable items, bool isOneToOne) diff --git a/FreeSql/Internal/CommonExpression.cs b/FreeSql/Internal/CommonExpression.cs index c806edd3..eefbd853 100644 --- a/FreeSql/Internal/CommonExpression.cs +++ b/FreeSql/Internal/CommonExpression.cs @@ -154,6 +154,7 @@ namespace FreeSql.Internal { case TableRefType.ManyToMany: case TableRefType.OneToMany: + case TableRefType.ArrayToMany: continue; } if (_tables.Any(a => a.Alias == $"{map.First().Table.Alias}__{memProp.Name}") == false) continue; @@ -2194,6 +2195,8 @@ namespace FreeSql.Internal for (var tidx = 0; tidx < memberTbref.Columns.Count; tidx++) select.Where($"{select._tables[0].Alias}.{commonExp._common.QuoteSqlName(memberTbref.RefColumns[tidx].Attribute.Name)} = {omtReftbname}.{commonExp._common.QuoteSqlName(memberTbref.Columns[tidx].Attribute.Name)}"); break; + case TableRefType.ArrayToMany: + break; } } @@ -2241,6 +2244,8 @@ namespace FreeSql.Internal if (select != null) return; LocalInitSelectProvider(); continue; + case TableRefType.ArrayToMany: + continue; } } if (exp4.NodeType == ExpressionType.Call) diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs index e28b43d1..36cde5e9 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs @@ -430,6 +430,8 @@ namespace FreeSql.Internal.CommonProvider var curTb = _commonUtils.GetTableByEntity(exp.Type); _commonExpression.ExpressionWhereLambda(_tables, Expression.MakeMemberAccess(exp, curTb.Properties[curTb.ColumnsByCs.First().Value.CsName]), null, null, null); break; + case TableRefType.ArrayToMany: + break; } return this; } @@ -1172,6 +1174,8 @@ namespace FreeSql.Internal.CommonProvider dicList.Clear(); } break; + case TableRefType.ArrayToMany: + break; } }; diff --git a/FreeSql/Internal/Model/TableInfo.cs b/FreeSql/Internal/Model/TableInfo.cs index 7de85216..2496d63c 100644 --- a/FreeSql/Internal/Model/TableInfo.cs +++ b/FreeSql/Internal/Model/TableInfo.cs @@ -150,6 +150,6 @@ namespace FreeSql.Internal.Model } public enum TableRefType { - OneToOne, ManyToOne, OneToMany, ManyToMany + OneToOne, ManyToOne, OneToMany, ManyToMany, ArrayToMany } } \ No newline at end of file diff --git a/FreeSql/Internal/UtilsExpressionTree.cs b/FreeSql/Internal/UtilsExpressionTree.cs index a6e0b71d..271edc49 100644 --- a/FreeSql/Internal/UtilsExpressionTree.cs +++ b/FreeSql/Internal/UtilsExpressionTree.cs @@ -593,7 +593,7 @@ namespace FreeSql.Internal } catch (Exception ex) { - throw new Exception(CoreStrings.LazyLoading_CompilationError(trytbTypeName, ex.Message, cscode)); ; + throw new Exception(CoreStrings.LazyLoading_CompilationError(trytbTypeName, ex.Message, cscode)); } var type = assembly.GetExportedTypes()/*.DefinedTypes*/.Where(a => a.FullName.EndsWith(trytbTypeLazyName)).FirstOrDefault(); trytb.TypeLazy = type; @@ -989,111 +989,215 @@ namespace FreeSql.Internal } } else - { //One To Many - List bindColumns = new List(); - if (pnvBind != null) + { + var isArrayToMany = false; + var lmbdWhere = isLazy ? new StringBuilder() : null; + //Pgsql Array[] To Many + if (common._orm.Ado.DataType == DataType.PostgreSQL) { - foreach (var bi in pnvBind) + //class User { + // public int[] RoleIds { get; set; } + // [Navigate(nameof(RoleIds))] + // public Role[] Roles { get; set; } + //} + //class Role { + // [Navigate(nameof(User.RoleIds))] + // public User[] Users { get; set; } + //} + ColumnInfo trycol = null; + if (tbref.Primarys.Length == 1) { - if (tbref.ColumnsByCs.TryGetValue(bi, out var trybindcol) == false) + if (pnvBind?.Length == 1) { - nvref.Exception = new Exception(CoreStrings.Navigation_ParsingError_NotFound_Property(trytbTypeName, pnv.Name, tbrefTypeName, bi)); + if (trytb.ColumnsByCs.TryGetValue(pnvBind[0], out trycol)) + { + if (trycol.CsType.IsArray == true && tbref.Primarys[0].CsType.NullableTypeOrThis() != trycol.CsType.GetElementType().NullableTypeOrThis()) + { + nvref.Exception = new Exception($"导航属性 {trytbTypeName}.{pnv.Name} 特性 [Navigate] 解析错误,{trytbTypeName}.{trycol.CsName} 数组元素 与 {tbrefTypeName}.{tbref.Primarys[0].CsName} 类型不符"); + trytb.AddOrUpdateTableRef(pnv.Name, nvref); + //if (isLazy) throw nvref.Exception; + } + } + } + if (nvref.Exception == null && trycol == null) + { + var findtbrefPkCsName = tbref.Primarys[0].CsName.TrimStart('_'); + if (findtbrefPkCsName.StartsWith(trytb.Type.Name, StringComparison.CurrentCultureIgnoreCase)) findtbrefPkCsName = findtbrefPkCsName.Substring(trytb.Type.Name.Length).TrimStart('_'); + var findtrytb = pnv.Name; + if (findtrytb.EndsWith($"{tbref.CsName}s", StringComparison.CurrentCultureIgnoreCase)) findtrytb = findtrytb.Substring(0, findtrytb.Length - tbref.CsName.Length - 1); + findtrytb += tbref.CsName; + if ( + tbref.ColumnsByCs.TryGetValue($"{findtrytb}{findtbrefPkCsName}", out trycol) == false && //骆峰命名 + tbref.ColumnsByCs.TryGetValue($"{findtrytb}_{findtbrefPkCsName}", out trycol) == false //下划线命名 + ) + { + } + if (trycol != null && tbref.Primarys[0].CsType.NullableTypeOrThis() != trycol.CsType.GetElementType().NullableTypeOrThis()) + trycol = null; + } + isArrayToMany = trycol != null; + if (isArrayToMany) + { + lmbdWhere.Append("this.").Append(trycol.CsName).Append(".Contains(a.").Append(tbref.Primarys[0].CsName).Append(")"); + nvref.Columns.Add(trycol); + nvref.RefColumns.Add(tbref.Primarys[0]); + nvref.RefEntityType = tbref.Type; + nvref.RefType = TableRefType.ArrayToMany; + trytb.AddOrUpdateTableRef(pnv.Name, nvref); + } + } + + if (nvref.Exception == null && trytb.Primarys.Length == 1 && isArrayToMany == false) + { + if (pnvBind?.Length == 1) + { + if (tbref.ColumnsByCs.TryGetValue(pnvBind[0], out trycol)) + { + if (trycol.CsType.IsArray == true && trytb.Primarys[0].CsType.NullableTypeOrThis() != trycol.CsType.GetElementType().NullableTypeOrThis()) + { + nvref.Exception = new Exception($"导航属性 {trytbTypeName}.{pnv.Name} 特性 [Navigate] 解析错误,{trytbTypeName}.{trytb.Primarys[0].CsName} 与 {tbrefTypeName}.{trycol.CsName} 数组元素类型不符"); + trytb.AddOrUpdateTableRef(pnv.Name, nvref); + //if (isLazy) throw nvref.Exception; + } + } + } + if (nvref.Exception == null && trycol == null) + { + var findtrytbPkCsName = trytb.Primarys[0].CsName.TrimStart('_'); + if (findtrytbPkCsName.StartsWith(trytb.Type.Name, StringComparison.CurrentCultureIgnoreCase)) findtrytbPkCsName = findtrytbPkCsName.Substring(trytb.Type.Name.Length).TrimStart('_'); + var findtrytb = pnv.Name; + if (findtrytb.EndsWith($"{tbref.CsName}s", StringComparison.CurrentCultureIgnoreCase)) findtrytb = findtrytb.Substring(0, findtrytb.Length - tbref.CsName.Length - 1); + findtrytb += trytb.CsName; + if ( + tbref.ColumnsByCs.TryGetValue($"{findtrytb}{findtrytbPkCsName}", out trycol) == false && //骆峰命名 + tbref.ColumnsByCs.TryGetValue($"{findtrytb}_{findtrytbPkCsName}", out trycol) == false //下划线命名 + ) + { + } + if (trycol != null && trytb.Primarys[0].CsType.NullableTypeOrThis() != trycol.CsType.GetElementType().NullableTypeOrThis()) + trycol = null; + } + isArrayToMany = trycol != null; + if (isArrayToMany) + { + lmbdWhere.Append("a.").Append(trycol.CsName).Append(".Contains(this.").Append(trytb.Primarys[0].CsName).Append(")"); + nvref.Columns.Add(tbref.Primarys[0]); + nvref.RefColumns.Add(trycol); + nvref.RefEntityType = tbref.Type; + nvref.RefType = TableRefType.ArrayToMany; + trytb.AddOrUpdateTableRef(pnv.Name, nvref); + } + } + + } + + PropertyInfo refprop = null; + if (isArrayToMany == false) + { + List bindColumns = new List(); + //One To Many + if (pnvBind != null) + { + foreach (var bi in pnvBind) + { + if (tbref.ColumnsByCs.TryGetValue(bi, out var trybindcol) == false) + { + nvref.Exception = new Exception(CoreStrings.Navigation_ParsingError_NotFound_Property(trytbTypeName, pnv.Name, tbrefTypeName, bi)); + trytb.AddOrUpdateTableRef(pnv.Name, nvref); + //if (isLazy) throw nvref.Exception; + break; + } + bindColumns.Add(trybindcol); + } + } + + var refcols = tbref.Properties.Where(z => z.Value.PropertyType == trytb.Type); + refprop = refcols.Count() == 1 ? refcols.First().Value : null; + + if (nvref.Exception == null && bindColumns.Any() && bindColumns.Count != trytb.Primarys.Length) + { + nvref.Exception = new Exception(CoreStrings.Navigation_Bind_Number_Different(trytbTypeName, pnv.Name, bindColumns.Count, trytb.Primarys.Length)); + trytb.AddOrUpdateTableRef(pnv.Name, nvref); + //if (isLazy) throw nvref.Exception; + } + if (trytb.Primarys.Length > 1) + { + if (trytb.Primarys.Select(a => a.CsType.NullableTypeOrThis()).Distinct().Count() == trytb.Primarys.Length) + { + var pkList = trytb.Primarys.ToList(); + bindColumns.Sort((a, b) => pkList.FindIndex(c => c.CsType.NullableTypeOrThis() == a.CsType.NullableTypeOrThis()).CompareTo(pkList.FindIndex(c => c.CsType.NullableTypeOrThis() == b.CsType.NullableTypeOrThis()))); + } + else if (string.Compare(string.Join(",", trytb.Primarys.Select(a => a.CsName).OrderBy(a => a)), string.Join(",", bindColumns.Select(a => a.CsName).OrderBy(a => a)), true) == 0) + { + var pkList = trytb.Primarys.ToList(); + bindColumns.Sort((a, b) => pkList.FindIndex(c => string.Compare(c.CsName, a.CsName, true) == 0).CompareTo(pkList.FindIndex(c => string.Compare(c.CsName, b.CsName, true) == 0))); + } + } + for (var a = 0; nvref.Exception == null && 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 = pnv.Name; + if (findtrytb.EndsWith($"{tbref.CsName}s", StringComparison.CurrentCultureIgnoreCase)) findtrytb = findtrytb.Substring(0, findtrytb.Length - tbref.CsName.Length - 1); + findtrytb += trytb.CsName; + + var trycol = bindColumns.Any() ? bindColumns[a] : null; + if (trycol == null && + tbref.ColumnsByCs.TryGetValue($"{findtrytb}{findtrytbPkCsName}", out trycol) == false && //骆峰命名 + tbref.ColumnsByCs.TryGetValue($"{findtrytb}_{findtrytbPkCsName}", out trycol) == false //下划线命名 + ) + { + 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.NullableTypeOrThis() != trytb.Primarys[a].CsType.NullableTypeOrThis()) + { + nvref.Exception = new Exception(CoreStrings.OneToMany_ParsingError_InconsistentType(trytbTypeName, pnv.Name, trytb.CsName, trytb.Primarys[a].CsName, tbref.CsName, trycol.CsName)); trytb.AddOrUpdateTableRef(pnv.Name, nvref); //if (isLazy) throw nvref.Exception; break; } - bindColumns.Add(trybindcol); - } - } - - PropertyInfo refprop = null; - var refcols = tbref.Properties.Where(z => z.Value.PropertyType == trytb.Type); - refprop = refcols.Count() == 1 ? refcols.First().Value : null; - var lmbdWhere = isLazy ? new StringBuilder() : null; - - if (nvref.Exception == null && bindColumns.Any() && bindColumns.Count != trytb.Primarys.Length) - { - nvref.Exception = new Exception(CoreStrings.Navigation_Bind_Number_Different(trytbTypeName, pnv.Name, bindColumns.Count, trytb.Primarys.Length)); - trytb.AddOrUpdateTableRef(pnv.Name, nvref); - //if (isLazy) throw nvref.Exception; - } - if (trytb.Primarys.Length > 1) - { - if (trytb.Primarys.Select(a => a.CsType.NullableTypeOrThis()).Distinct().Count() == trytb.Primarys.Length) - { - var pkList = trytb.Primarys.ToList(); - bindColumns.Sort((a, b) => pkList.FindIndex(c => c.CsType.NullableTypeOrThis() == a.CsType.NullableTypeOrThis()).CompareTo(pkList.FindIndex(c => c.CsType.NullableTypeOrThis() == b.CsType.NullableTypeOrThis()))); - } - else if (string.Compare(string.Join(",", trytb.Primarys.Select(a => a.CsName).OrderBy(a => a)), string.Join(",", bindColumns.Select(a => a.CsName).OrderBy(a => a)), true) == 0) - { - var pkList = trytb.Primarys.ToList(); - bindColumns.Sort((a, b) => pkList.FindIndex(c => string.Compare(c.CsName, a.CsName, true) == 0).CompareTo(pkList.FindIndex(c => string.Compare(c.CsName, b.CsName, true) == 0))); - } - } - for (var a = 0; nvref.Exception == null && 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 = pnv.Name; - if (findtrytb.EndsWith($"{tbref.CsName}s", StringComparison.CurrentCultureIgnoreCase)) findtrytb = findtrytb.Substring(0, findtrytb.Length - tbref.CsName.Length - 1); - findtrytb += trytb.CsName; - - var trycol = bindColumns.Any() ? bindColumns[a] : null; - if (trycol == null && - tbref.ColumnsByCs.TryGetValue($"{findtrytb}{findtrytbPkCsName}", out trycol) == false && //骆峰命名 - tbref.ColumnsByCs.TryGetValue($"{findtrytb}_{findtrytbPkCsName}", out trycol) == false //下划线命名 - ) - { - if (refprop != null && - tbref.ColumnsByCs.TryGetValue($"{refprop.Name}{findtrytbPkCsName}", out trycol) == false && //骆峰命名 - tbref.ColumnsByCs.TryGetValue($"{refprop.Name}_{findtrytbPkCsName}", out trycol) == false) //下划线命名 + if (trycol == null) { - + nvref.Exception = new Exception(CoreStrings.OneToMany_NotFound_CorrespondingField(trytbTypeName, pnv.Name, tbref.CsName, findtrytb, findtrytbPkCsName) + + (refprop == null ? "" : CoreStrings.OneToMany_UseNavigate(refprop.Name, findtrytbPkCsName))); + trytb.AddOrUpdateTableRef(pnv.Name, nvref); + //if (isLazy) throw nvref.Exception; + break; } - } - if (trycol != null && trycol.CsType.NullableTypeOrThis() != trytb.Primarys[a].CsType.NullableTypeOrThis()) - { - nvref.Exception = new Exception(CoreStrings.OneToMany_ParsingError_InconsistentType(trytbTypeName, pnv.Name, trytb.CsName, trytb.Primarys[a].CsName, tbref.CsName, trycol.CsName)); - trytb.AddOrUpdateTableRef(pnv.Name, nvref); - //if (isLazy) throw nvref.Exception; - break; - } - if (trycol == null) - { - nvref.Exception = new Exception(CoreStrings.OneToMany_NotFound_CorrespondingField(trytbTypeName, pnv.Name, tbref.CsName, findtrytb, findtrytbPkCsName) - + (refprop == null ? "" : CoreStrings.OneToMany_UseNavigate(refprop.Name, findtrytbPkCsName))); - trytb.AddOrUpdateTableRef(pnv.Name, nvref); - //if (isLazy) throw nvref.Exception; - break; - } - nvref.Columns.Add(trytb.Primarys[a]); - nvref.RefColumns.Add(trycol); + nvref.Columns.Add(trytb.Primarys[a]); + nvref.RefColumns.Add(trycol); - if (isLazy && nvref.Exception == null) - { - if (a > 0) lmbdWhere.Append(" && "); - lmbdWhere.Append("a.").Append(trycol.CsName).Append(" == this.").Append(trytb.Primarys[a].CsName); + if (isLazy && nvref.Exception == null) + { + if (a > 0) lmbdWhere.Append(" && "); + lmbdWhere.Append("a.").Append(trycol.CsName).Append(" == this.").Append(trytb.Primarys[a].CsName); - if (refprop == null) - { //加载成功后,把列表对应的导航属性值设置为 this,比如 Select().ToOne().Topics 下的 TopicType 属性值全部为 this - 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; + if (refprop == null) + { //加载成功后,把列表对应的导航属性值设置为 this,比如 Select().ToOne().Topics 下的 TopicType 属性值全部为 this + 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; + } } } } - } - if (nvref.Columns.Count > 0 && nvref.RefColumns.Count > 0) - { - nvref.RefEntityType = tbref.Type; - nvref.RefType = TableRefType.OneToMany; - trytb.AddOrUpdateTableRef(pnv.Name, nvref); - } + if (nvref.Columns.Count > 0 && nvref.RefColumns.Count > 0) + { + nvref.RefEntityType = tbref.Type; + nvref.RefType = TableRefType.OneToMany; + trytb.AddOrUpdateTableRef(pnv.Name, nvref); + } + } if (isLazy) { cscode.Append(" private bool __lazy__").Append(pnv.Name).AppendLine(" = false;") @@ -1133,7 +1237,8 @@ namespace FreeSql.Internal } } else - { //一对一、多对一 + { + //一对一、多对一 var tbref = pnv.PropertyType == trytb.Type ? trytb : GetTableByEntity(pnv.PropertyType, common); //可能是父子关系 if (tbref == null) return; if (tbref.Primarys.Any() == false)