- 增加 [Navigate(xx, TempPrimary = xx)] 与非主键关联;(仅支持查询)

This commit is contained in:
2881099 2023-03-02 15:46:45 +08:00
parent c6556a47ab
commit da7bb7c74d
14 changed files with 243 additions and 101 deletions

View File

@ -377,7 +377,7 @@ namespace FreeSql
continue;
}
if (cascade == false) continue;
var tbref = table.GetTableRef(prop.Name, false);
var tbref = table.GetTableRef(prop.Name, false, false);
if (tbref == null) continue;
var boundaryAttr = GetPropertyBoundaryAttribute(prop, boundaryName);
if (boundaryAttr?.Break == true) continue;

View File

@ -18,7 +18,7 @@
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
<DelaySign>false</DelaySign>
<Version>1.0.6</Version>
<Version>3.2.690-preview20230302</Version>
</PropertyGroup>
<ItemGroup>
@ -26,7 +26,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="FreeSql.DbContext" Version="3.2.666" />
<ProjectReference Include="..\..\FreeSql.DbContext\FreeSql.DbContext.csproj" />
</ItemGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|netstandard2.0|AnyCPU'">

View File

@ -151,7 +151,7 @@ namespace FreeSql
if (_table.Properties.TryGetValue(propertyName, out var prop) == false) throw new KeyNotFoundException(DbContextStrings.NotFound_Property(_table.Type.FullName, propertyName));
if (_table.ColumnsByCsIgnore.ContainsKey(propertyName)) throw new ArgumentException(DbContextStrings.TypeHasSetProperty_IgnoreAttribute(_table.Type.FullName, propertyName));
var tref = _table.GetTableRef(propertyName, true);
var tref = _table.GetTableRef(propertyName, true, false);
if (tref == null) return;
switch (tref.RefType)
{
@ -209,7 +209,7 @@ namespace FreeSql
if (_table.ColumnsByCsIgnore.ContainsKey(prop.Name)) return;
if (_table.ColumnsByCs.ContainsKey(prop.Name)) return;
var tref = _table.GetTableRef(prop.Name, false); //防止非正常的导航属性报错
var tref = _table.GetTableRef(prop.Name, false, false); //防止非正常的导航属性报错
if (tref == null) return;
DbSet<object> refSet = null;
switch (tref.RefType)

View File

@ -162,7 +162,7 @@ namespace FreeSql
if (_table.Properties.TryGetValue(propertyName, out var prop) == false) throw new KeyNotFoundException(DbContextStrings.NotFound_Property(_table.Type.FullName, propertyName));
if (_table.ColumnsByCsIgnore.ContainsKey(propertyName)) throw new ArgumentException(DbContextStrings.TypeHasSetProperty_IgnoreAttribute(_table.Type.FullName, propertyName));
var tref = _table.GetTableRef(propertyName, true);
var tref = _table.GetTableRef(propertyName, true, false);
if (tref == null) return;
switch (tref.RefType)
{
@ -220,7 +220,7 @@ namespace FreeSql
if (_table.ColumnsByCsIgnore.ContainsKey(prop.Name)) return;
if (_table.ColumnsByCs.ContainsKey(prop.Name)) return;
var tref = _table.GetTableRef(prop.Name, false); //防止非正常的导航属性报错
var tref = _table.GetTableRef(prop.Name, false, false); //防止非正常的导航属性报错
if (tref == null) return;
DbSet<object> refSet = null;
switch (tref.RefType)

View File

@ -22,6 +22,13 @@ namespace FreeSql.DataAnnotations
/// _________________public List&lt;Topic&gt; Topics { get; set; }<para></para>
/// </summary>
public string Bind { get; set; }
/// <summary>
/// 与非主键进行关联,仅支持 OneToMany、ManyToOne<para></para>
/// 使用方法参考 Bind 属性
/// </summary>
public string TempPrimary { get; set; }
/// <summary>
/// 手工绑定 ManyToMany 导航关系
/// </summary>

View File

@ -60,10 +60,12 @@ namespace FreeSql.DataAnnotations
/// <param name="bind"></param>
/// <param name="manyToMany">多对多关系的中间实体类型</param>
/// <returns></returns>
public TableFluent Navigate(string proto, string bind, Type manyToMany = null)
public TableFluent Navigate(string proto, string bind, Type manyToMany = null) => NavigateInternal(proto, bind, null, manyToMany);
public TableFluent Navigate(string proto, string bind, string tempPrimary) => NavigateInternal(proto, bind, tempPrimary, null);
TableFluent NavigateInternal(string proto, string bind, string tempPrimary, Type manyToMany)
{
if (_properties.TryGetValue(proto, out var tryProto) == false) throw new KeyNotFoundException(CoreStrings.NotFound_Property(proto));
var nav = new NavigateAttribute { Bind = bind, ManyToMany = manyToMany };
var nav = new NavigateAttribute { Bind = bind, TempPrimary = tempPrimary, ManyToMany = manyToMany };
_table._navigates.AddOrUpdate(tryProto.Name, nav, (name, old) => nav);
return this;
}
@ -148,18 +150,22 @@ namespace FreeSql.DataAnnotations
/// <param name="bind"></param>
/// <param name="manyToMany">多对多关系的中间实体类型</param>
/// <returns></returns>
public TableFluent<T> Navigate<TProto>(Expression<Func<T, TProto>> proto, string bind, Type manyToMany = null)
public TableFluent<T> Navigate<TProto>(Expression<Func<T, TProto>> proto, string bind, Type manyToMany = null) => NavigateInternal(proto, bind, null, manyToMany);
public TableFluent<T> Navigate<TProto>(Expression<Func<T, TProto>> proto, string bind, string tempPrimary) => NavigateInternal(proto, bind, tempPrimary, null);
TableFluent<T> NavigateInternal<TProto>(Expression<Func<T, TProto>> proto, string bind, string tempPrimary, Type manyToMany = null)
{
var exp = proto?.Body;
if (exp.NodeType == ExpressionType.Convert) exp = (exp as UnaryExpression)?.Operand;
var member = (exp as MemberExpression)?.Member;
if (member == null) throw new FormatException(CoreStrings.Bad_Expression_Format(proto));
return Navigate(member.Name, bind, manyToMany);
return NavigateInternal(member.Name, bind, tempPrimary, manyToMany);
}
public TableFluent<T> Navigate(string proto, string bind, Type manyToMany = null)
public TableFluent<T> Navigate(string proto, string bind, Type manyToMany = null) => NavigateInternal(proto, bind, null, manyToMany);
public TableFluent<T> Navigate(string proto, string bind, string tempPrimary) => NavigateInternal(proto, bind, tempPrimary, null);
TableFluent<T> NavigateInternal(string proto, string bind, string tempPrimary, Type manyToMany)
{
if (_properties.TryGetValue(proto, out var tryProto) == false) throw new KeyNotFoundException(CoreStrings.NotFound_PropertyName(proto));
var nav = new NavigateAttribute { Bind = bind, ManyToMany = manyToMany };
var nav = new NavigateAttribute { Bind = bind, TempPrimary = tempPrimary, ManyToMany = manyToMany };
_table._navigates.AddOrUpdate(tryProto.Name, nav, (name, old) => nav);
return this;
}

View File

@ -409,7 +409,7 @@ public static partial class FreeSqlGlobalExtensions
#endif
return list;
}
var tbtr = t1tb.GetTableRef(props[0], true);
var tbtr = t1tb.GetTableRef(props[0], true, true);
if (tbtr == null) throw new ArgumentException(CoreStrings.ParameterError_NotValid_Navigation(nameof(property)));
var reftb = orm.CodeFirst.GetTableByEntity(t1exp.Type);
var refsel = orm.Select<object>().AsType(t1exp.Type) as Select1Provider<object>;

View File

@ -385,6 +385,12 @@
_________________public List&lt;Topic&gt; Topics { get; set; }<para></para>
</summary>
</member>
<member name="P:FreeSql.DataAnnotations.NavigateAttribute.TempPrimary">
<summary>
与非主键进行关联,仅支持 OneToMany、ManyToOne<para></para>
使用方法参考 Bind 属性
</summary>
</member>
<member name="P:FreeSql.DataAnnotations.NavigateAttribute.ManyToMany">
<summary>
手工绑定 ManyToMany 导航关系

View File

@ -375,29 +375,29 @@ namespace FreeSql
switch (_nameConvertType)
{
case NameConvertType.ToLower:
ret.Aop.ConfigEntity += (_, e) => e.ModifyResult.Name = e.ModifyResult.Name?.ToLower();
ret.Aop.ConfigEntity += (_, e) => { if (string.IsNullOrWhiteSpace(e.ModifyResult.AsTable)) e.ModifyResult.Name = e.ModifyResult.Name?.ToLower(); };
ret.Aop.ConfigEntityProperty += (_, e) => e.ModifyResult.Name = e.ModifyResult.Name?.ToLower();
ret.CodeFirst.IsSyncStructureToLower = true;
break;
case NameConvertType.ToUpper:
ret.Aop.ConfigEntity += (_, e) => e.ModifyResult.Name = e.ModifyResult.Name?.ToUpper();
ret.Aop.ConfigEntity += (_, e) => { if (string.IsNullOrWhiteSpace(e.ModifyResult.AsTable)) e.ModifyResult.Name = e.ModifyResult.Name?.ToUpper(); };
ret.Aop.ConfigEntityProperty += (_, e) => e.ModifyResult.Name = e.ModifyResult.Name?.ToUpper();
ret.CodeFirst.IsSyncStructureToUpper = true;
break;
case NameConvertType.PascalCaseToUnderscore:
ret.Aop.ConfigEntity += (_, e) => e.ModifyResult.Name = PascalCaseToUnderScore(e.ModifyResult.Name);
ret.Aop.ConfigEntity += (_, e) => { if (string.IsNullOrWhiteSpace(e.ModifyResult.AsTable)) e.ModifyResult.Name = PascalCaseToUnderScore(e.ModifyResult.Name); };
ret.Aop.ConfigEntityProperty += (_, e) => e.ModifyResult.Name = PascalCaseToUnderScore(e.ModifyResult.Name);
break;
case NameConvertType.PascalCaseToUnderscoreWithLower:
ret.Aop.ConfigEntity += (_, e) => e.ModifyResult.Name = PascalCaseToUnderScore(e.ModifyResult.Name)?.ToLower();
ret.Aop.ConfigEntity += (_, e) => { if (string.IsNullOrWhiteSpace(e.ModifyResult.AsTable)) e.ModifyResult.Name = PascalCaseToUnderScore(e.ModifyResult.Name)?.ToLower(); };
ret.Aop.ConfigEntityProperty += (_, e) => e.ModifyResult.Name = PascalCaseToUnderScore(e.ModifyResult.Name)?.ToLower();
break;
case NameConvertType.PascalCaseToUnderscoreWithUpper:
ret.Aop.ConfigEntity += (_, e) => e.ModifyResult.Name = PascalCaseToUnderScore(e.ModifyResult.Name)?.ToUpper();
ret.Aop.ConfigEntity += (_, e) => { if (string.IsNullOrWhiteSpace(e.ModifyResult.AsTable)) e.ModifyResult.Name = PascalCaseToUnderScore(e.ModifyResult.Name)?.ToUpper(); };
ret.Aop.ConfigEntityProperty += (_, e) => e.ModifyResult.Name = PascalCaseToUnderScore(e.ModifyResult.Name)?.ToUpper();
break;
//case NameConvertType.UnderscoreToPascalCase:
// ret.Aop.ConfigEntity += (_, e) => e.ModifyResult.Name = UnderScorePascalCase(e.ModifyResult.Name);
// ret.Aop.ConfigEntity += (_, e) => { if (string.IsNullOrWhiteSpace(e.ModifyResult.AsTable)) e.ModifyResult.Name = UnderScorePascalCase(e.ModifyResult.Name); };
// ret.Aop.ConfigEntityProperty += (_, e) => e.ModifyResult.Name = UnderScorePascalCase(e.ModifyResult.Name);
// break;
default:

View File

@ -1428,7 +1428,7 @@ namespace FreeSql.Internal
}
var parm123Tb = _common.GetTableByEntity(asSelectParentExp.Type);
var parm123Ref = parm123Tb.GetTableRef(asSelectParentExp1.Member.Name, true);
var parm123Ref = parm123Tb.GetTableRef(asSelectParentExp1.Member.Name, true, true);
if (parm123Ref != null)
{
if (parm123Ref.RefType == TableRefType.PgArrayToMany)
@ -1902,7 +1902,7 @@ namespace FreeSql.Internal
{ //导航条件OneToOne、ManyToOne
var firstTb = tsc._tables.First().Table;
var parentTb = _common.GetTableByEntity(mp.Expression.Type);
var parentTbRef = parentTb?.GetTableRef(mp.Member.Name, tsc.style == ExpressionStyle.AsSelect);
var parentTbRef = parentTb?.GetTableRef(mp.Member.Name, tsc.style == ExpressionStyle.AsSelect, true);
if (parentTbRef != null)
{
Expression navCondExp = null;
@ -2015,7 +2015,7 @@ namespace FreeSql.Internal
}
if (tb2.ColumnsByCsIgnore.ContainsKey(mp2.Member.Name))
throw new ArgumentException(CoreStrings.Ignored_Check_Confirm_PublicGetSet(tb2.DbName, mp2.Member.Name));
if (tb2.GetTableRef(mp2.Member.Name, false) != null)
if (tb2.GetTableRef(mp2.Member.Name, false, true) != null)
throw new ArgumentException(CoreStrings.Navigation_Missing_AsSelect(tb2.DbName, mp2.Member.Name));
throw new ArgumentException(CoreStrings.NotFound_Column(tb2.DbName, mp2.Member.Name));
}
@ -2718,7 +2718,7 @@ namespace FreeSql.Internal
}
if (select != null) return;
memberExp = tmpExp;
memberTbref = exp3Tb.GetTableRef(memberExp.Member.Name, false);
memberTbref = exp3Tb.GetTableRef(memberExp.Member.Name, false, true);
if (memberTbref == null) return;
switch (memberTbref.RefType)
{

View File

@ -503,7 +503,7 @@ namespace FreeSql.Internal.CommonProvider
if (memExp == null) throw new ArgumentException($"{CoreStrings.Cannot_Resolve_ExpressionTree(nameof(property))}2");
var parTb = _commonUtils.GetTableByEntity(memExp.Expression.Type);
if (parTb == null) throw new ArgumentException($"{CoreStrings.Cannot_Resolve_ExpressionTree(nameof(property))}3");
var parTbref = parTb.GetTableRef(memExp.Member.Name, true);
var parTbref = parTb.GetTableRef(memExp.Member.Name, true, true);
if (parTbref == null) throw new ArgumentException(CoreStrings.Not_Valid_Navigation_Property(nameof(property)));
switch (parTbref.RefType)
{
@ -682,7 +682,7 @@ namespace FreeSql.Internal.CommonProvider
var tbrefOneToManyColumns = new List<List<MemberExpression>>(); //临时 OneToMany 三个表关联,第三个表需要前两个表确定
if (whereExp == null)
{
tbref = tb.GetTableRef(collMem.Member.Name, true);
tbref = tb.GetTableRef(collMem.Member.Name, true, true);
if (tbref == null) throw new Exception(CoreStrings.IncludeMany_NotValid_Navigation(tb.Type.DisplayCsharp(), collMem.Member.Name));
}
else

View File

@ -352,6 +352,7 @@ namespace FreeSql.Internal
if (dicConfigEntity.TryGetValue(type, out var trytb) && trytb._navigates.TryGetValue(proto.Name, out var trynav))
{
if (!string.IsNullOrEmpty(trynav.Bind)) attr.Bind = trynav.Bind;
if (!string.IsNullOrEmpty(trynav.TempPrimary)) attr.TempPrimary = trynav.TempPrimary;
if (trynav.ManyToMany != null) attr.ManyToMany = trynav.ManyToMany;
}
break;
@ -362,6 +363,7 @@ namespace FreeSql.Internal
trynav = tryattrobj as NavigateAttribute;
if (trynav == null) continue;
if (!string.IsNullOrEmpty(trynav.Bind)) attr.Bind = trynav.Bind;
if (!string.IsNullOrEmpty(trynav.TempPrimary)) attr.TempPrimary = trynav.TempPrimary;
if (trynav.ManyToMany != null) attr.ManyToMany = trynav.ManyToMany;
}
break;

View File

@ -38,7 +38,7 @@ namespace FreeSql.Internal.Model
{
_refs.AddOrUpdate(propertyName, tbref, (ok, ov) => tbref);
}
public TableRef GetTableRef(string propertyName, bool isThrowException)
public TableRef GetTableRef(string propertyName, bool isThrowException, bool isCascadeQuery = true)
{
if (_refs.TryGetValue(propertyName, out var tryref) == false) return null;
if (tryref.Exception != null)
@ -46,6 +46,18 @@ namespace FreeSql.Internal.Model
if (isThrowException) throw tryref.Exception;
return null;
}
if (isCascadeQuery == false && tryref.IsTempPrimary == true)
{
if (isThrowException)
{
switch (tryref.RefType)
{
case TableRefType.OneToMany: throw new Exception($"[Navigate(\"{string.Join(",", tryref.RefColumns.Select(a => a.CsName))}\", TempPrimary = \"{string.Join(",", tryref.Columns.Select(a => a.CsName))}\")] Only cascade query are supported");
case TableRefType.ManyToOne: throw new Exception($"[Navigate(\"{string.Join(",", tryref.Columns.Select(a => a.CsName))}\", TempPrimary = \"{string.Join(",", tryref.RefColumns.Select(a => a.CsName))}\")] Only cascade query are supported");
}
}
return null;
}
return tryref;
}
public IEnumerable<KeyValuePair<string, TableRef>> GetAllTableRef() => _refs;
@ -160,6 +172,7 @@ namespace FreeSql.Internal.Model
public List<ColumnInfo> RefColumns { get; set; } = new List<ColumnInfo>();
public Exception Exception { get; set; }
public bool IsTempPrimary { get; set; }
}
public enum TableRefType
{

View File

@ -623,12 +623,188 @@ namespace FreeSql.Internal
var pnvAttr = common.GetEntityNavigateAttribute(trytb.Type, pnv);
var pnvBind = pnvAttr?.Bind?.Split(',').Select(a => a.Trim()).Where(a => !string.IsNullOrEmpty(a)).ToArray();
var pnvBindTempPrimary = pnvAttr?.TempPrimary?.Split(',').Select(a => a.Trim()).Where(a => !string.IsNullOrEmpty(a)).ToArray();
var nvref = new TableRef();
nvref.Property = pnv;
//List 或 ICollection一对多、多对多
var propElementType = pnv.PropertyType.GetGenericArguments().FirstOrDefault() ?? pnv.PropertyType.GetElementType();
var propTypeIsObservableCollection = propElementType != null && pnv.PropertyType == typeof(ObservableCollection<>).MakeGenericType(propElementType);
#region islazy
void LocalManyLazyLoadingCode(PropertyInfo refprop, string cscodeExtLogic1, string cscodeExtLogic2, string lmbdWhere)
{
cscode.Append(" private bool __lazy__").Append(pnv.Name).AppendLine(" = false;")
.Append(" ").Append(propModification).Append(" override ").Append(propTypeName).Append(" ").Append(pnv.Name).AppendLine(" {");
if (vp?.Item2 == true)
{ //get 重写
cscode.Append(" ").Append(propGetModification).Append(" get {\r\n")
.Append(cscodeExtLogic1)
.Append(" if (base.").Append(pnv.Name).Append(" == null && __lazy__").Append(pnv.Name).AppendLine(" == false) {");
if (nvref.Exception == null)
{
cscode.Append(" var loc2 = __fsql_orm__.Select<").Append(propElementType.DisplayCsharp()).Append(">().Where(a => ").Append(lmbdWhere).AppendLine(").ToList();")
.Append(cscodeExtLogic2)
.Append(" base.").Append(pnv.Name).Append(" = ").AppendLine(propTypeIsObservableCollection ? $"new ObservableCollection<{propElementType.DisplayCsharp()}>(loc2);" : "loc2;");
if (refprop != null)
{
cscode.Append(" foreach (var loc1 in base.").Append(pnv.Name).AppendLine(")")
.Append(" loc1.").Append(refprop.Name).AppendLine(" = this;");
}
cscode.Append(" __lazy__").Append(pnv.Name).AppendLine(" = true;");
}
else
cscode.Append(" throw new Exception(\"").Append(nvref.Exception.Message.Replace("\r\n", "\\r\\n").Replace("\"", "\\\"")).AppendLine("\");");
cscode
.Append(" }\r\n")
.Append(" return base.").Append(pnv.Name).AppendLine(";")
.Append(" }\r\n");
}
if (vp?.Item3 == true)
{ //set 重写
cscode.Append(" ").Append(propSetModification).Append(" set {\r\n")
.Append(" base.").Append(pnv.Name).AppendLine(" = value;")
.Append(" __lazy__").Append(pnv.Name).AppendLine(" = true;")
.Append(" }\r\n");
}
cscode.AppendLine(" }");
}
void LocalLazyLoadingCode(string lmbdWhere)
{
cscode.Append(" private bool __lazy__").Append(pnv.Name).AppendLine(" = false;")
.Append(" ").Append(propModification).Append(" override ").Append(propTypeName).Append(" ").Append(pnv.Name).AppendLine(" {");
if (vp?.Item2 == true)
{ //get 重写
cscode.Append(" ").Append(propGetModification).Append(" get {\r\n")
.Append(" if (base.").Append(pnv.Name).Append(" == null && __lazy__").Append(pnv.Name).AppendLine(" == false) {");
if (nvref.Exception == null)
cscode.Append(" var loc3 = __fsql_orm__.Select<").Append(propTypeName).Append(">().Where(a => ").Append(lmbdWhere).AppendLine(").ToOne();")
.Append(" base.").Append(pnv.Name).AppendLine(" = loc3;")
.Append(" __lazy__").Append(pnv.Name).AppendLine(" = true;");
else
cscode.Append(" throw new Exception(\"").Append(nvref.Exception.Message.Replace("\r\n", "\\r\\n").Replace("\"", "\\\"")).AppendLine("\");");
cscode
.Append(" }\r\n")
.Append(" return base.").Append(pnv.Name).AppendLine(";")
.Append(" }\r\n");
}
if (vp?.Item3 == true)
{ //set 重写
cscode.Append(" ").Append(propSetModification).Append(" set {\r\n")
.Append(" base.").Append(pnv.Name).AppendLine(" = value;")
.Append(" __lazy__").Append(pnv.Name).AppendLine(" = true;")
.Append(" }\r\n");
}
cscode.AppendLine(" }");
}
#endregion
#region [Navigate("xx", Ref = "...")]
if (pnvBind != null && pnvBindTempPrimary != null && pnvBind.Length > 0 && pnvBindTempPrimary.Length == pnvBind.Length)
{
nvref.IsTempPrimary = true;
TableInfo tbref = null;
//OneToMany
if (propElementType != null)
{
if (typeof(IEnumerable).IsAssignableFrom(pnv.PropertyType) == false) return;
tbref = propElementType == trytb.Type ? trytb : GetTableByEntity(propElementType, common); //可能是父子关系
}
else
{
tbref = pnv.PropertyType == trytb.Type ? trytb : GetTableByEntity(pnv.PropertyType, common); //可能是父子关系
}
if (tbref == null) return;
var tbrefTypeName = tbref.Type.DisplayCsharp();
Func<TableInfo, string[], string, List<ColumnInfo>> getBindColumns = (locTb, locBind, locFindTypeName) =>
{
var locRet = new List<ColumnInfo>();
foreach (var bi in locBind)
{
if (locTb.ColumnsByCs.TryGetValue(bi, out var trybindcol) == false)
{
nvref.Exception = new Exception(CoreStrings.Navigation_ParsingError_NotFound_Property(trytbTypeName, pnv.Name, locFindTypeName, bi));
trytb.AddOrUpdateTableRef(pnv.Name, nvref);
//if (isLazy) throw nvref.Exception;
break;
}
locRet.Add(trybindcol);
}
return locRet;
};
if (propElementType != null)
{
var bindColumns = getBindColumns(tbref, pnvBind, tbrefTypeName);
var bindColumnsTempPrimary = getBindColumns(trytb, pnvBindTempPrimary, trytbTypeName);
var lmbdWhere = isLazy ? new StringBuilder() : null;
for (var a = 0; nvref.Exception == null && a < bindColumnsTempPrimary.Count; a++)
{
if (bindColumnsTempPrimary[a].CsType.NullableTypeOrThis() != bindColumns[a].CsType.NullableTypeOrThis())
{
nvref.Exception = new Exception(CoreStrings.OneToMany_ParsingError_InconsistentType(trytbTypeName, pnv.Name, trytb.CsName, bindColumnsTempPrimary[a].CsName, tbref.CsName, bindColumns[a].CsName));
trytb.AddOrUpdateTableRef(pnv.Name, nvref);
//if (isLazy) throw nvref.Exception;
break;
}
nvref.Columns.Add(bindColumnsTempPrimary[a]);
nvref.RefColumns.Add(bindColumns[a]);
if (isLazy && nvref.Exception == null)
{
if (a > 0) lmbdWhere.Append(" && ");
lmbdWhere.Append("a.").Append(bindColumns[a].CsName).Append(" == this.").Append(bindColumnsTempPrimary[a].CsName);
}
}
if (nvref.Columns.Count > 0 && nvref.RefColumns.Count > 0)
{
nvref.RefEntityType = tbref.Type;
nvref.RefType = TableRefType.OneToMany;
trytb.AddOrUpdateTableRef(pnv.Name, nvref);
}
if (isLazy) LocalManyLazyLoadingCode(null, null, null, lmbdWhere.ToString());
}
else
{
var bindColumns = getBindColumns(trytb, pnvBind, trytbTypeName);
var bindColumnsTempPrimary = getBindColumns(tbref, pnvBindTempPrimary, tbrefTypeName);
var lmbdWhere = isLazy ? new StringBuilder() : null;
for (var a = 0; nvref.Exception == null && a < bindColumnsTempPrimary.Count; a++)
{
if (bindColumns[a].CsType.NullableTypeOrThis() != bindColumnsTempPrimary[a].CsType.NullableTypeOrThis())
{
nvref.Exception = new Exception(CoreStrings.Navigation_ParsingError_InconsistentType(trytbTypeName, pnv.Name, trytb.CsName, bindColumns[a].CsName, tbref.CsName, bindColumnsTempPrimary[a].CsName));
trytb.AddOrUpdateTableRef(pnv.Name, nvref);
//if (isLazy) throw nvref.Exception;
break;
}
nvref.Columns.Add(bindColumns[a]);
nvref.RefColumns.Add(bindColumnsTempPrimary[a]);
if (isLazy && nvref.Exception == null)
{
if (a > 0) lmbdWhere.Append(" && ");
lmbdWhere.Append("a.").Append(bindColumnsTempPrimary[a].CsName).Append(" == this.").Append(bindColumns[a].CsName);
}
}
if (nvref.Columns.Count > 0 && nvref.RefColumns.Count > 0)
{
nvref.RefEntityType = tbref.Type;
nvref.RefType = TableRefType.ManyToOne;
trytb.AddOrUpdateTableRef(pnv.Name, nvref);
}
if (isLazy) LocalLazyLoadingCode(lmbdWhere.ToString());
}
}
#endregion
if (propElementType != null)
{
if (typeof(IEnumerable).IsAssignableFrom(pnv.PropertyType) == false) return;
@ -780,11 +956,11 @@ namespace FreeSql.Internal
TableRef trytbTf = null;
try
{
trytbTf = tbmid.GetTableRef(midTypePropsTrytb.Name, true);
trytbTf = tbmid.GetTableRef(midTypePropsTrytb.Name, true, false);
if (trytbTf == null)
{
AddTableRef(common, tbmid, midTypePropsTrytb, false, null, null);
trytbTf = tbmid.GetTableRef(midTypePropsTrytb.Name, true);
trytbTf = tbmid.GetTableRef(midTypePropsTrytb.Name, true, false);
}
}
catch (Exception ex)
@ -827,11 +1003,11 @@ namespace FreeSql.Internal
TableRef tbrefTf = null;
try
{
tbrefTf = tbmid.GetTableRef(midTypePropsTbref.Name, true);
tbrefTf = tbmid.GetTableRef(midTypePropsTbref.Name, true, false);
if (tbrefTf == null)
{
AddTableRef(common, tbmid, midTypePropsTbref, false, null, null);
tbrefTf = tbmid.GetTableRef(midTypePropsTbref.Name, true);
tbrefTf = tbmid.GetTableRef(midTypePropsTbref.Name, true, false);
}
}
catch (Exception ex)
@ -1225,45 +1401,7 @@ namespace FreeSql.Internal
}
}
if (isLazy)
{
cscode.Append(" private bool __lazy__").Append(pnv.Name).AppendLine(" = false;")
.Append(" ").Append(propModification).Append(" override ").Append(propTypeName).Append(" ").Append(pnv.Name).AppendLine(" {");
if (vp?.Item2 == true)
{ //get 重写
cscode.Append(" ").Append(propGetModification).Append(" get {\r\n")
.Append(cscodeExtLogic1)
.Append(" if (base.").Append(pnv.Name).Append(" == null && __lazy__").Append(pnv.Name).AppendLine(" == false) {");
if (nvref.Exception == null)
{
cscode.Append(" var loc2 = __fsql_orm__.Select<").Append(propElementType.DisplayCsharp()).Append(">().Where(a => ").Append(lmbdWhere.ToString()).AppendLine(").ToList();")
.Append(cscodeExtLogic2)
.Append(" base.").Append(pnv.Name).Append(" = ").AppendLine(propTypeIsObservableCollection ? $"new ObservableCollection<{propElementType.DisplayCsharp()}>(loc2);" : "loc2;");
if (refprop != null)
{
cscode.Append(" foreach (var loc1 in base.").Append(pnv.Name).AppendLine(")")
.Append(" loc1.").Append(refprop.Name).AppendLine(" = this;");
}
cscode.Append(" __lazy__").Append(pnv.Name).AppendLine(" = true;");
}
else
cscode.Append(" throw new Exception(\"").Append(nvref.Exception.Message.Replace("\r\n", "\\r\\n").Replace("\"", "\\\"")).AppendLine("\");");
cscode
.Append(" }\r\n")
.Append(" return base.").Append(pnv.Name).AppendLine(";")
.Append(" }\r\n");
}
if (vp?.Item3 == true)
{ //set 重写
cscode.Append(" ").Append(propSetModification).Append(" set {\r\n")
.Append(" base.").Append(pnv.Name).AppendLine(" = value;")
.Append(" __lazy__").Append(pnv.Name).AppendLine(" = true;")
.Append(" }\r\n");
}
cscode.AppendLine(" }");
}
if (isLazy) LocalManyLazyLoadingCode(refprop, cscodeExtLogic1, cscodeExtLogic2, lmbdWhere.ToString());
}
}
else
@ -1385,37 +1523,7 @@ namespace FreeSql.Internal
nvref.RefType = isOnoToOne ? TableRefType.OneToOne : TableRefType.ManyToOne;
trytb.AddOrUpdateTableRef(pnv.Name, nvref);
}
if (isLazy)
{
cscode.Append(" private bool __lazy__").Append(pnv.Name).AppendLine(" = false;")
.Append(" ").Append(propModification).Append(" override ").Append(propTypeName).Append(" ").Append(pnv.Name).AppendLine(" {");
if (vp?.Item2 == true)
{ //get 重写
cscode.Append(" ").Append(propGetModification).Append(" get {\r\n")
.Append(" if (base.").Append(pnv.Name).Append(" == null && __lazy__").Append(pnv.Name).AppendLine(" == false) {");
if (nvref.Exception == null)
cscode.Append(" var loc3 = __fsql_orm__.Select<").Append(propTypeName).Append(">().Where(a => ").Append(lmbdWhere.ToString()).AppendLine(").ToOne();")
.Append(" base.").Append(pnv.Name).AppendLine(" = loc3;")
.Append(" __lazy__").Append(pnv.Name).AppendLine(" = true;");
else
cscode.Append(" throw new Exception(\"").Append(nvref.Exception.Message.Replace("\r\n", "\\r\\n").Replace("\"", "\\\"")).AppendLine("\");");
cscode
.Append(" }\r\n")
.Append(" return base.").Append(pnv.Name).AppendLine(";")
.Append(" }\r\n");
}
if (vp?.Item3 == true)
{ //set 重写
cscode.Append(" ").Append(propSetModification).Append(" set {\r\n")
.Append(" base.").Append(pnv.Name).AppendLine(" = value;")
.Append(" __lazy__").Append(pnv.Name).AppendLine(" = true;")
.Append(" }\r\n");
}
cscode.AppendLine(" }");
}
if (isLazy) LocalLazyLoadingCode(lmbdWhere.ToString());
}
}
static Lazy<MethodInfo> MethodLazyLoadingComplier = new Lazy<MethodInfo>(() =>