- 增加 ISelect Cancel 用于取消本次查询;

- 增加 IncludeIf/IncludeByPropertyNameIf 方法;
This commit is contained in:
2881099 2020-11-12 22:03:17 +08:00
parent f25e56be58
commit f93261d8e2
8 changed files with 108 additions and 25 deletions

View File

@ -509,14 +509,5 @@
<param name="that"></param>
<returns></returns>
</member>
<member name="M:Microsoft.Extensions.DependencyInjection.FreeSqlRepositoryDependencyInjection.AddFreeRepository(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Action{FreeSql.FluentDataFilter},System.Reflection.Assembly[])">
<summary>
批量注入 Repository可以参考代码自行调整
</summary>
<param name="services"></param>
<param name="globalDataFilter"></param>
<param name="assemblies"></param>
<returns></returns>
</member>
</members>
</doc>

View File

@ -1160,6 +1160,15 @@
<param name="column"></param>
<returns></returns>
</member>
<member name="M:FreeSql.SqlExt.FindInSet``1(``0,System.String)">
<summary>
MySql find_in_set(str, strlist)
</summary>
<typeparam name="TValue"></typeparam>
<param name="str"></param>
<param name="strlist"></param>
<returns></returns>
</member>
<member name="M:FreeSql.SqlExt.StringAgg(System.Object,System.Object)">
<summary>
PostgreSQL string_agg(.., ..)
@ -1639,6 +1648,17 @@
使用属性名作为字段别名
</summary>
</member>
<member name="M:FreeSql.ISelect0`2.Cancel(System.Func{System.Boolean})">
<summary>
控制取消本次查询<para></para>
* 不会产生额外的异常<para></para>
* 取消成功,则不执行 SQL 命令<para></para>
* 取消成功,直接返回没有记录时候的返回值<para></para>
* 取消成功,如 List&lt;T&gt; 返回 0 元素列表,不是 null仍然是旧机制<para></para>
</summary>
<param name="cancel">返回 true则不会执行 SQL 命令</param>
<returns></returns>
</member>
<member name="M:FreeSql.ISelect0`2.WithTransaction(System.Data.Common.DbTransaction)">
<summary>
指定事务对象
@ -2331,6 +2351,15 @@
<param name="navigateSelector">选择一个导航属性</param>
<returns></returns>
</member>
<member name="M:FreeSql.ISelect`1.IncludeIf``1(System.Boolean,System.Linq.Expressions.Expression{System.Func{`0,``0}})">
<summary>
贪婪加载导航属性,如果查询中已经使用了 a.Parent.Parent 类似表达式,则可以无需此操作
</summary>
<typeparam name="TNavigate"></typeparam>
<param name="condition">true 时生效</param>
<param name="navigateSelector">选择一个导航属性</param>
<returns></returns>
</member>
<member name="M:FreeSql.ISelect`1.IncludeMany``1(System.Linq.Expressions.Expression{System.Func{`0,System.Collections.Generic.IEnumerable{``0}}},System.Action{FreeSql.ISelect{``0}})">
<summary>
贪婪加载集合的导航属性其实是分两次查询ToList 后进行了数据重装<para></para>
@ -2352,6 +2381,14 @@
<param name="property"></param>
<returns></returns>
</member>
<member name="M:FreeSql.ISelect`1.IncludeByPropertyNameIf(System.Boolean,System.String)">
<summary>
按属性名字符串进行 Include/IncludeMany 操作
</summary>
<param name="condition">true 时生效</param>
<param name="property"></param>
<returns></returns>
</member>
<member name="M:FreeSql.ISelect`1.WithSql(System.String,System.Object)">
<summary>
实现 select .. from ( select ... from t ) a 这样的功能<para></para>

View File

@ -30,6 +30,17 @@ namespace FreeSql
Task<long> CountAsync(CancellationToken cancellationToken = default);
#endif
/// <summary>
/// 控制取消本次查询<para></para>
/// * 不会产生额外的异常<para></para>
/// * 取消成功,则不执行 SQL 命令<para></para>
/// * 取消成功,直接返回没有记录时候的返回值<para></para>
/// * 取消成功,如 List&lt;T&gt; 返回 0 元素列表,不是 null仍然是旧机制<para></para>
/// </summary>
/// <param name="cancel">返回 true则不会执行 SQL 命令</param>
/// <returns></returns>
TSelect Cancel(Func<bool> cancel);
/// <summary>
/// 指定事务对象
/// </summary>

View File

@ -321,6 +321,14 @@ namespace FreeSql
/// <returns></returns>
ISelect<T1> Include<TNavigate>(Expression<Func<T1, TNavigate>> navigateSelector) where TNavigate : class;
/// <summary>
/// 贪婪加载导航属性,如果查询中已经使用了 a.Parent.Parent 类似表达式,则可以无需此操作
/// </summary>
/// <typeparam name="TNavigate"></typeparam>
/// <param name="condition">true 时生效</param>
/// <param name="navigateSelector">选择一个导航属性</param>
/// <returns></returns>
ISelect<T1> IncludeIf<TNavigate>(bool condition, Expression<Func<T1, TNavigate>> navigateSelector) where TNavigate : class;
/// <summary>
/// 贪婪加载集合的导航属性其实是分两次查询ToList 后进行了数据重装<para></para>
/// 文档https://github.com/2881099/FreeSql/wiki/%e8%b4%aa%e5%a9%aa%e5%8a%a0%e8%bd%bd#%E5%AF%BC%E8%88%AA%E5%B1%9E%E6%80%A7-onetomanymanytomany
/// </summary>
@ -340,6 +348,13 @@ namespace FreeSql
/// <param name="property"></param>
/// <returns></returns>
ISelect<T1> IncludeByPropertyName(string property);
/// <summary>
/// 按属性名字符串进行 Include/IncludeMany 操作
/// </summary>
/// <param name="condition">true 时生效</param>
/// <param name="property"></param>
/// <returns></returns>
ISelect<T1> IncludeByPropertyNameIf(bool condition, string property);
/// <summary>
/// 实现 select .. from ( select ... from t ) a 这样的功能<para></para>

View File

@ -42,6 +42,7 @@ namespace FreeSql.Internal.CommonProvider
public bool _distinct;
public Expression _selectExpression;
public List<GlobalFilter.Item> _whereGlobalFilter;
public Func<bool> _cancel;
int _disposeCounter;
~Select0Provider()
@ -61,6 +62,7 @@ namespace FreeSql.Internal.CommonProvider
_includeInfo.Clear();
_selectExpression = null;
_whereGlobalFilter?.Clear();
_cancel = null;
}
public static void CopyData(Select0Provider from, Select0Provider to, ReadOnlyCollection<ParameterExpression> lambParms)
@ -119,6 +121,7 @@ namespace FreeSql.Internal.CommonProvider
to._distinct = from._distinct;
to._selectExpression = from._selectExpression;
to._whereGlobalFilter = new List<GlobalFilter.Item>(from._whereGlobalFilter.ToArray());
to._cancel = from._cancel;
}
public Expression ConvertStringPropertyToExpression(string property, bool fromFirstTable = false)
@ -183,6 +186,12 @@ namespace FreeSql.Internal.CommonProvider
return this as TSelect;
}
public TSelect Cancel(Func<bool> cancel)
{
_cancel = cancel;
return this as TSelect;
}
public TSelect WithTransaction(DbTransaction transaction)
{
_transaction = transaction;

View File

@ -21,11 +21,12 @@ namespace FreeSql.Internal.CommonProvider
{
public DataTable ToDataTable(string field = null)
{
DataTable ret = null;
if (_cancel?.Invoke() == true) return ret;
var sql = this.ToSql(field);
var dbParms = _params.ToArray();
var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, _tables[0].Table, Aop.CurdType.Select, sql, dbParms);
_orm.Aop.CurdBeforeHandler?.Invoke(this, before);
DataTable ret = null;
Exception exception = null;
try
{
@ -46,12 +47,13 @@ namespace FreeSql.Internal.CommonProvider
public List<TTuple> ToList<TTuple>(string field)
{
var ret = new List<TTuple>();
if (_cancel?.Invoke() == true) return ret;
var sql = this.ToSql(field);
var type = typeof(TTuple);
var dbParms = _params.ToArray();
var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, _tables[0].Table, Aop.CurdType.Select, sql, dbParms);
_orm.Aop.CurdBeforeHandler?.Invoke(this, before);
var ret = new List<TTuple>();
Exception exception = null;
try
{
@ -81,10 +83,11 @@ namespace FreeSql.Internal.CommonProvider
}
internal List<T1> ToListAfPrivate(string sql, GetAllFieldExpressionTreeInfo af, ReadAnonymousTypeOtherInfo[] otherData)
{
var ret = new List<T1>();
if (_cancel?.Invoke() == true) return ret;
var dbParms = _params.ToArray();
var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, _tables[0].Table, Aop.CurdType.Select, sql, dbParms);
_orm.Aop.CurdBeforeHandler?.Invoke(this, before);
var ret = new List<T1>();
var retCount = 0;
Exception exception = null;
try
@ -133,6 +136,7 @@ namespace FreeSql.Internal.CommonProvider
#region ToChunk
internal void ToListAfChunkPrivate(int chunkSize, Action<FetchCallbackArgs<List<T1>>> chunkDone, string sql, GetAllFieldExpressionTreeInfo af, ReadAnonymousTypeOtherInfo[] otherData)
{
if (_cancel?.Invoke() == true) return;
var dbParms = _params.ToArray();
var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, _tables[0].Table, Aop.CurdType.Select, sql, dbParms);
_orm.Aop.CurdBeforeHandler?.Invoke(this, before);
@ -208,6 +212,7 @@ namespace FreeSql.Internal.CommonProvider
internal void ToListMrChunkPrivate<TReturn>(int chunkSize, Action<FetchCallbackArgs<List<TReturn>>> chunkDone, string sql, ReadAnonymousTypeAfInfo af)
{
if (_cancel?.Invoke() == true) return;
var type = typeof(TReturn);
var dbParms = _params.ToArray();
var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, _tables[0].Table, Aop.CurdType.Select, sql, dbParms);
@ -266,12 +271,14 @@ namespace FreeSql.Internal.CommonProvider
{
if (keySelector == null) throw new ArgumentNullException(nameof(keySelector));
if (elementSelector == null) throw new ArgumentNullException(nameof(elementSelector));
var ret = new Dictionary<TKey, TElement>();
if (_cancel?.Invoke() == true) return ret;
var af = this.GetAllFieldExpressionTreeLevel2();
var sql = this.ToSql(af.Field);
var dbParms = _params.ToArray();
var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, _tables[0].Table, Aop.CurdType.Select, sql, dbParms);
_orm.Aop.CurdBeforeHandler?.Invoke(this, before);
var ret = new Dictionary<TKey, TElement>();
Exception exception = null;
try
{
@ -297,11 +304,12 @@ namespace FreeSql.Internal.CommonProvider
internal List<TReturn> ToListMrPrivate<TReturn>(string sql, ReadAnonymousTypeAfInfo af, ReadAnonymousTypeOtherInfo[] otherData)
{
var ret = new List<TReturn>();
if (_cancel?.Invoke() == true) return ret;
var type = typeof(TReturn);
var dbParms = _params.ToArray();
var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, _tables[0].Table, Aop.CurdType.Select, sql, dbParms);
_orm.Aop.CurdBeforeHandler?.Invoke(this, before);
var ret = new List<TReturn>();
var retCount = 0;
Exception exception = null;
try
@ -715,12 +723,13 @@ namespace FreeSql.Internal.CommonProvider
}
public int InternalInsertInto<TTargetEntity>(string tableName, Expression select)
{
int ret = 0;
if (_cancel?.Invoke() == true) return ret;
var sql = this.InternalGetInsertIntoToSql<TTargetEntity>(tableName, select);
var dbParms = _params.ToArray();
var tb = _orm.CodeFirst.GetTableByEntity(typeof(TTargetEntity));
var before = new Aop.CurdBeforeEventArgs(tb.Type, tb, Aop.CurdType.Insert, sql, dbParms);
_orm.Aop.CurdBeforeHandler?.Invoke(this, before);
int ret = 0;
Exception exception = null;
try
{
@ -741,11 +750,12 @@ namespace FreeSql.Internal.CommonProvider
protected DataTable InternalToDataTable(Expression select)
{
DataTable ret = null;
if (_cancel?.Invoke() == true) return ret;
var sql = this.InternalToSql<int>(select, FieldAliasOptions.AsProperty); //DataTable 使用 AsProperty
var dbParms = _params.ToArray();
var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, _tables[0].Table, Aop.CurdType.Select, sql, dbParms);
_orm.Aop.CurdBeforeHandler?.Invoke(this, before);
DataTable ret = null;
Exception exception = null;
try
{
@ -790,11 +800,12 @@ namespace FreeSql.Internal.CommonProvider
#else
async public Task<DataTable> ToDataTableAsync(string field, CancellationToken cancellationToken)
{
DataTable ret = null;
if (_cancel?.Invoke() == true) return ret;
var sql = this.ToSql(field);
var dbParms = _params.ToArray();
var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, _tables[0].Table, Aop.CurdType.Select, sql, dbParms);
_orm.Aop.CurdBeforeHandler?.Invoke(this, before);
DataTable ret = null;
Exception exception = null;
try
{
@ -815,12 +826,13 @@ namespace FreeSql.Internal.CommonProvider
async public Task<List<TTuple>> ToListAsync<TTuple>(string field, CancellationToken cancellationToken)
{
var ret = new List<TTuple>();
if (_cancel?.Invoke() == true) return ret;
var sql = this.ToSql(field);
var type = typeof(TTuple);
var dbParms = _params.ToArray();
var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, _tables[0].Table, Aop.CurdType.Select, sql, dbParms);
_orm.Aop.CurdBeforeHandler?.Invoke(this, before);
var ret = new List<TTuple>();
Exception exception = null;
try
{
@ -852,10 +864,11 @@ namespace FreeSql.Internal.CommonProvider
async internal Task<List<T1>> ToListAfPrivateAsync(string sql, GetAllFieldExpressionTreeInfo af, ReadAnonymousTypeOtherInfo[] otherData, CancellationToken cancellationToken)
{
var ret = new List<T1>();
if (_cancel?.Invoke() == true) return ret;
var dbParms = _params.ToArray();
var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, _tables[0].Table, Aop.CurdType.Select, sql, dbParms);
_orm.Aop.CurdBeforeHandler?.Invoke(this, before);
var ret = new List<T1>();
var retCount = 0;
Exception exception = null;
try
@ -909,12 +922,14 @@ namespace FreeSql.Internal.CommonProvider
{
if (keySelector == null) throw new ArgumentNullException(nameof(keySelector));
if (elementSelector == null) throw new ArgumentNullException(nameof(elementSelector));
var ret = new Dictionary<TKey, TElement>();
if (_cancel?.Invoke() == true) return ret;
var af = this.GetAllFieldExpressionTreeLevel2();
var sql = this.ToSql(af.Field);
var dbParms = _params.ToArray();
var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, _tables[0].Table, Aop.CurdType.Select, sql, dbParms);
_orm.Aop.CurdBeforeHandler?.Invoke(this, before);
var ret = new Dictionary<TKey, TElement>();
Exception exception = null;
try
{
@ -941,11 +956,12 @@ namespace FreeSql.Internal.CommonProvider
async internal Task<List<TReturn>> ToListMrPrivateAsync<TReturn>(string sql, ReadAnonymousTypeAfInfo af, ReadAnonymousTypeOtherInfo[] otherData, CancellationToken cancellationToken)
{
var ret = new List<TReturn>();
if (_cancel?.Invoke() == true) return ret;
var type = typeof(TReturn);
var dbParms = _params.ToArray();
var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, _tables[0].Table, Aop.CurdType.Select, sql, dbParms);
_orm.Aop.CurdBeforeHandler?.Invoke(this, before);
var ret = new List<TReturn>();
var retCount = 0;
Exception exception = null;
try
@ -1006,12 +1022,13 @@ namespace FreeSql.Internal.CommonProvider
async public Task<int> InternalInsertIntoAsync<TTargetEntity>(string tableName, Expression select, CancellationToken cancellationToken)
{
int ret = 0;
if (_cancel?.Invoke() == true) return ret;
var sql = this.InternalGetInsertIntoToSql<TTargetEntity>(tableName, select);
var dbParms = _params.ToArray();
var tb = _orm.CodeFirst.GetTableByEntity(typeof(TTargetEntity));
var before = new Aop.CurdBeforeEventArgs(tb.Type, tb, Aop.CurdType.Insert, sql, dbParms);
_orm.Aop.CurdBeforeHandler?.Invoke(this, before);
int ret = 0;
Exception exception = null;
try
{
@ -1032,11 +1049,12 @@ namespace FreeSql.Internal.CommonProvider
async protected Task<DataTable> InternalToDataTableAsync(Expression select, CancellationToken cancellationToken)
{
DataTable ret = null;
if (_cancel?.Invoke() == true) return ret;
var sql = this.InternalToSql<int>(select, FieldAliasOptions.AsProperty); //DataTable 使用 AsProperty
var dbParms = _params.ToArray();
var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, _tables[0].Table, Aop.CurdType.Select, sql, dbParms);
_orm.Aop.CurdBeforeHandler?.Invoke(this, before);
DataTable ret = null;
Exception exception = null;
try
{

View File

@ -393,6 +393,7 @@ namespace FreeSql.Internal.CommonProvider
public int InsertInto<TTargetEntity>(string tableName, Expression<Func<T1, TTargetEntity>> select) where TTargetEntity : class => base.InternalInsertInto<TTargetEntity>(tableName, select);
public ISelect<T1> IncludeByPropertyNameIf(bool condition, string property) => condition ? IncludeByPropertyName(property) : this;
public ISelect<T1> IncludeByPropertyName(string property)
{
var exp = ConvertStringPropertyToExpression(property, true);
@ -424,6 +425,7 @@ namespace FreeSql.Internal.CommonProvider
}
bool _isIncluded = false;
public ISelect<T1> IncludeIf<TNavigate>(bool condition, Expression<Func<T1, TNavigate>> navigateSelector) where TNavigate : class => condition ? Include(navigateSelector) : this;
public ISelect<T1> Include<TNavigate>(Expression<Func<T1, TNavigate>> navigateSelector) where TNavigate : class
{
var expBody = navigateSelector?.Body;

View File

@ -171,7 +171,7 @@ namespace FreeSql.Internal.CommonProvider
return this;
}
public long Count() => long.TryParse(string.Concat(_orm.Ado.ExecuteScalar(_select._connection, _select._transaction, CommandType.Text, $"select count(1) from ({this.ToSql($"1{_comonExp._common.FieldAsAlias("as1")}")}) fta", _select._commandTimeout, _select._params.ToArray())), out var trylng) ? trylng : default(long);
public long Count() => _select._cancel?.Invoke() == true ? 0 : long.TryParse(string.Concat(_orm.Ado.ExecuteScalar(_select._connection, _select._transaction, CommandType.Text, $"select count(1) from ({this.ToSql($"1{_comonExp._common.FieldAsAlias("as1")}")}) fta", _select._commandTimeout, _select._params.ToArray())), out var trylng) ? trylng : default(long);
public ISelectGrouping<TKey, TValue> Count(out long count)
{
count = this.Count();
@ -200,7 +200,7 @@ namespace FreeSql.Internal.CommonProvider
#if net40
#else
async public Task<long> CountAsync(CancellationToken cancellationToken = default) => long.TryParse(string.Concat(await _orm.Ado.ExecuteScalarAsync(_select._connection, _select._transaction, CommandType.Text, $"select count(1) from ({this.ToSql($"1{_comonExp._common.FieldAsAlias("as1")}")}) fta", _select._commandTimeout, _select._params.ToArray(), cancellationToken)), out var trylng) ? trylng : default(long);
async public Task<long> CountAsync(CancellationToken cancellationToken = default) => _select._cancel?.Invoke() == true ? 0 : long.TryParse(string.Concat(await _orm.Ado.ExecuteScalarAsync(_select._connection, _select._transaction, CommandType.Text, $"select count(1) from ({this.ToSql($"1{_comonExp._common.FieldAsAlias("as1")}")}) fta", _select._commandTimeout, _select._params.ToArray(), cancellationToken)), out var trylng) ? trylng : default(long);
public Task<List<TReturn>> ToListAsync<TReturn>(Expression<Func<ISelectGroupingAggregate<TKey, TValue>, TReturn>> select, CancellationToken cancellationToken = default)
{