- 增加 IncludeByPropertyName 按属性名进行 Include/IncludeMany 操作;#278

This commit is contained in:
2881099 2020-11-04 18:03:47 +08:00
parent 856ecf279d
commit b701ad8421
5 changed files with 71 additions and 2 deletions

View File

@ -191,6 +191,10 @@ namespace FreeSql.Tests
{ {
[Column(IsIdentity = true)] [Column(IsIdentity = true)]
public int? Id { get; set; } public int? Id { get; set; }
public string name { get; set; }
[Navigate(nameof(tshop01.cateId))]
public List<tshop01> tshops { get; set; }
} }
public class tshop01 public class tshop01
{ {
@ -203,7 +207,28 @@ namespace FreeSql.Tests
[Fact] [Fact]
public void Test03() public void Test03()
{ {
g.sqlite.Delete<tcate01>().Where("1=1").ExecuteAffrows();
g.sqlite.Delete<tshop01>().Where("1=1").ExecuteAffrows();
var tshoprepo = g.sqlite.GetRepository<tcate01>();
tshoprepo.DbContextOptions.EnableAddOrUpdateNavigateList = true;
tshoprepo.Insert(new tcate01[]
{
new tcate01 { name = "tcate1", tshops = new List<tshop01>{ new tshop01(), new tshop01(), new tshop01() } },
new tcate01 { name = "tcate1", tshops = new List<tshop01>{ new tshop01(), new tshop01(), new tshop01() } }
});
var tshop01sql = g.sqlite.Select<tshop01>().Include(a => a.cate).ToSql(); var tshop01sql = g.sqlite.Select<tshop01>().Include(a => a.cate).ToSql();
var tshop02sql = g.sqlite.Select<tshop01>().IncludeByPropertyName("cate").ToSql();
var tshop03sql = g.sqlite.Select<tshop01>().IncludeMany(a => a.cate.tshops).ToSql();
var tshop04sql = g.sqlite.Select<tshop01>().IncludeByPropertyName("cate.tshops").ToSql();
var tshop01lst = g.sqlite.Select<tshop01>().Include(a => a.cate).ToList();
var tshop02lst = g.sqlite.Select<tshop01>().IncludeByPropertyName("cate").ToList();
var tshop03lst = g.sqlite.Select<tshop01>().IncludeMany(a => a.cate.tshops).ToList();
var tshop04lst = g.sqlite.Select<tshop01>().IncludeByPropertyName("cate.tshops").ToList();
var testisnullsql1 = g.sqlite.Select<t102>().Where(a => SqlExt.IsNull(a.isxx, false).Equals( true)).ToSql(); var testisnullsql1 = g.sqlite.Select<t102>().Where(a => SqlExt.IsNull(a.isxx, false).Equals( true)).ToSql();

View File

@ -2345,6 +2345,13 @@
<param name="then">即能 ThenInclude还可以二次过滤这个 EFCore 做不到?)</param> <param name="then">即能 ThenInclude还可以二次过滤这个 EFCore 做不到?)</param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:FreeSql.ISelect`1.IncludeByPropertyName(System.String)">
<summary>
按属性名字符串进行 Include/IncludeMany 操作
</summary>
<param name="property"></param>
<returns></returns>
</member>
<member name="M:FreeSql.ISelect`1.WithSql(System.String,System.Object)"> <member name="M:FreeSql.ISelect`1.WithSql(System.String,System.Object)">
<summary> <summary>
实现 select .. from ( select ... from t ) a 这样的功能<para></para> 实现 select .. from ( select ... from t ) a 这样的功能<para></para>

View File

@ -333,6 +333,13 @@ namespace FreeSql
/// <returns></returns> /// <returns></returns>
ISelect<T1> IncludeMany<TNavigate>(Expression<Func<T1, IEnumerable<TNavigate>>> navigateSelector, Action<ISelect<TNavigate>> then = null) where TNavigate : class; ISelect<T1> IncludeMany<TNavigate>(Expression<Func<T1, IEnumerable<TNavigate>>> navigateSelector, Action<ISelect<TNavigate>> then = null) where TNavigate : class;
/// <summary>
/// 按属性名字符串进行 Include/IncludeMany 操作
/// </summary>
/// <param name="property"></param>
/// <returns></returns>
ISelect<T1> IncludeByPropertyName(string property);
/// <summary> /// <summary>
/// 实现 select .. from ( select ... from t ) a 这样的功能<para></para> /// 实现 select .. from ( select ... from t ) a 这样的功能<para></para>
/// 使用 AsTable 方法也可以达到效果<para></para> /// 使用 AsTable 方法也可以达到效果<para></para>

View File

@ -121,13 +121,13 @@ namespace FreeSql.Internal.CommonProvider
to._whereGlobalFilter = new List<GlobalFilter.Item>(from._whereGlobalFilter.ToArray()); to._whereGlobalFilter = new List<GlobalFilter.Item>(from._whereGlobalFilter.ToArray());
} }
public Expression ConvertStringPropertyToExpression(string property) public Expression ConvertStringPropertyToExpression(string property, bool fromFirstTable = false)
{ {
if (string.IsNullOrEmpty(property)) return null; if (string.IsNullOrEmpty(property)) return null;
var field = property.Split('.').Select(a => a.Trim()).ToArray(); var field = property.Split('.').Select(a => a.Trim()).ToArray();
Expression exp = null; Expression exp = null;
if (field.Length == 1) if (field.Length == 1 && fromFirstTable == false)
{ {
foreach (var tb in _tables) foreach (var tb in _tables)
{ {

View File

@ -392,6 +392,36 @@ namespace FreeSql.Internal.CommonProvider
public int InsertInto<TTargetEntity>(string tableName, Expression<Func<T1, TTargetEntity>> select) where TTargetEntity : class => base.InternalInsertInto<TTargetEntity>(tableName, select); public int InsertInto<TTargetEntity>(string tableName, Expression<Func<T1, TTargetEntity>> select) where TTargetEntity : class => base.InternalInsertInto<TTargetEntity>(tableName, select);
public ISelect<T1> IncludeByPropertyName(string property)
{
var exp = ConvertStringPropertyToExpression(property, true);
if (exp == null) throw new ArgumentException($"{nameof(property)} 无法解析为表达式树");
var memExp = exp as MemberExpression;
if (memExp == null) throw new ArgumentException($"{nameof(property)} 无法解析为表达式树2");
var parTb = _commonUtils.GetTableByEntity(memExp.Expression.Type);
if (parTb == null) throw new ArgumentException($"{nameof(property)} 无法解析为表达式树3");
var parTbref = parTb.GetTableRef(memExp.Member.Name, true);
if (parTbref == null) throw new ArgumentException($"{nameof(property)} 不是有效的导航属性");
switch (parTbref.RefType)
{
case TableRefType.ManyToMany:
case TableRefType.OneToMany:
var funcType = typeof(Func<,>).MakeGenericType(_tables[0].Table.Type, typeof(IEnumerable<>).MakeGenericType(parTbref.RefEntityType));
var navigateSelector = Expression.Lambda(funcType, exp, _tables[0].Parameter);
var incMethod = this.GetType().GetMethod("IncludeMany");
if (incMethod == null) throw new Exception("运行时错误,反射获取 IncludeMany 方法失败");
incMethod.MakeGenericMethod(parTbref.RefEntityType).Invoke(this, new object[] { navigateSelector, null });
break;
case TableRefType.ManyToOne:
case TableRefType.OneToOne:
_isIncluded = true;
var curTb = _commonUtils.GetTableByEntity(exp.Type);
_commonExpression.ExpressionWhereLambda(_tables, Expression.MakeMemberAccess(exp, curTb.Properties[curTb.ColumnsByCs.First().Value.CsName]), null, null, null);
break;
}
return this;
}
bool _isIncluded = false; bool _isIncluded = false;
public ISelect<T1> Include<TNavigate>(Expression<Func<T1, TNavigate>> navigateSelector) where TNavigate : class public ISelect<T1> Include<TNavigate>(Expression<Func<T1, TNavigate>> navigateSelector) where TNavigate : class
{ {