init ArrayToMany

This commit is contained in:
2881099 2022-06-04 00:35:33 +08:00
parent fba96d7f2c
commit 8ca0414500
6 changed files with 223 additions and 105 deletions

View File

@ -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<object> 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<object>();
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<object>();
var addOrUpdateList = new List<object>();
foreach (var propValItem in propValEach)

View File

@ -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<object> 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<TableRef, PropertyInfo>(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<object> dbset, IEnumerable<object> items, bool isOneToOne)

View File

@ -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)

View File

@ -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;
}
};

View File

@ -150,6 +150,6 @@ namespace FreeSql.Internal.Model
}
public enum TableRefType
{
OneToOne, ManyToOne, OneToMany, ManyToMany
OneToOne, ManyToOne, OneToMany, ManyToMany, ArrayToMany
}
}

View File

@ -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<ColumnInfo> bindColumns = new List<ColumnInfo>();
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<ColumnInfo> bindColumns = new List<ColumnInfo>();
//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<TopicType>().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<TopicType>().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)