using FreeSql.Internal.CommonProvider; using FreeSql.Internal.Model; using System; using System.Collections.Generic; using System.Data; using System.Data.Common; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Text; using System.Threading; using System.Threading.Tasks; namespace FreeSql { public interface ISelectedQuery { Select0Provider SelectOwner { get; } #if net40 #else Task> ToListAsync(CancellationToken cancellationToken = default); Task ToOneAsync(CancellationToken cancellationToken = default); Task FirstAsync(CancellationToken cancellationToken = default); Task AnyAsync(CancellationToken cancellationToken = default); Task CountAsync(CancellationToken cancellationToken = default); #endif List ToList(); TOut ToOne(); TOut First(); string ToSql(); bool Any(); long Count(); ISelectedQuery Count(out long count); ISelectedQuery Skip(int offset); ISelectedQuery Offset(int offset); ISelectedQuery Limit(int limit); ISelectedQuery Take(int limit); ISelectedQuery Page(int pageNumber, int pageSize); ISelectedQuery Where(Expression> exp); ISelectedQuery WhereIf(bool condition, Expression> exp); ISelectedQuery OrderBy(Expression> column); ISelectedQuery OrderByIf(bool condition, Expression> column, bool descending = false); ISelectedQuery OrderByDescending(Expression> column); } } namespace FreeSql.Internal.CommonProvider { public class SelectedQueryProvider : BaseDiyMemberExpression, ISelectedQuery { public Select0Provider _select; public CommonExpression _comonExp; public SelectedQueryProvider(Select0Provider select, Expression selector) { _select = select; _comonExp = _select._commonExpression; _map = new ReadAnonymousTypeInfo(); var field = new StringBuilder(); var index = -10000; //临时规则,不返回 as1 if (selector != null) _comonExp.ReadAnonymousField(_select._tables, _select._tableRule, field, _map, ref index, selector, null, null, _select._whereGlobalFilter, null, null, false); //不走 DTO 映射,不处理 IncludeMany _field = field.ToString(); } public override string ParseExp(Expression[] members) { ParseExpMapResult = null; if (members.Any() == false) { ParseExpMapResult = _map; return _map.DbField; } var read = _map; for (var a = 0; a < members.Length; a++) { read = read.Childs.Where(z => z.CsName == (members[a] as MemberExpression)?.Member.Name).FirstOrDefault(); if (read == null) return null; } ParseExpMapResult = read; return read.DbField; } public Select0Provider SelectOwner => _select; #if net40 #else public Task> ToListAsync(CancellationToken cancellationToken = default) { var method = _select.GetType().GetMethod("ToListMapReaderAsync", BindingFlags.Instance | BindingFlags.NonPublic); method = method.MakeGenericMethod(typeof(TOut)); return method.Invoke(_select, new object[] { new ReadAnonymousTypeAfInfo(_map, _field.Length > 0 ? _field.Remove(0, 2).ToString() : null), cancellationToken }) as Task>; } async public Task ToOneAsync(CancellationToken cancellationToken = default) => (await ToListAsync(cancellationToken)).FirstOrDefault(); public Task FirstAsync(CancellationToken cancellationToken = default) => ToOneAsync(cancellationToken); public Task AnyAsync(CancellationToken cancellationToken = default) { var method = _select.GetType().GetMethod("AnyAsync", new Type[] { typeof(CancellationToken) }); return method.Invoke(_select, new object[] { cancellationToken }) as Task; } public Task CountAsync(CancellationToken cancellationToken = default) { var method = _select.GetType().GetMethod("CountAsync", new Type[] { typeof(CancellationToken) }); return method.Invoke(_select, new object[] { cancellationToken }) as Task; } #endif public List ToList() { var method = _select.GetType().GetMethod("ToListMapReader", BindingFlags.Instance | BindingFlags.NonPublic); method = method.MakeGenericMethod(typeof(TOut)); return method.Invoke(_select, new object[] { new ReadAnonymousTypeAfInfo(_map, _field.Length > 0 ? _field.Remove(0, 2).ToString() : null) }) as List; } public TOut ToOne() => ToList().FirstOrDefault(); public TOut First() => ToOne(); public string ToSql() { var method = _select.GetType().GetMethod("ToSql", new[] { typeof(string) }); return method.Invoke(_select, new object[] { _field.Length > 0 ? _field.Remove(0, 2).ToString() : null }) as string; } public bool Any() { var method = _select.GetType().GetMethod("Any", new Type[0]); return (bool)method.Invoke(_select, new object[0]); } public long Count() { var method = _select.GetType().GetMethod("Count", new Type[0]); return (long)method.Invoke(_select, new object[0]); } public ISelectedQuery Count(out long count) { count = this.Count(); return this; } public ISelectedQuery Skip(int offset) { _select._skip = offset; return this; } public ISelectedQuery Offset(int offset) => Skip(offset); public ISelectedQuery Limit(int limit) => Take(limit); public ISelectedQuery Take(int limit) { _select._limit = limit; return this; } public ISelectedQuery Page(int pageNumber, int pageSize) { this.Skip(Math.Max(0, pageNumber - 1) * pageSize); return this.Limit(pageSize); } public ISelectedQuery OrderBy(Expression> column) => OrderByIf(true, column); public ISelectedQuery OrderByIf(bool condition, Expression> column, bool descending = false) { if (condition == false) return this; _lambdaParameter = column?.Parameters[0]; var sql = _comonExp.ExpressionWhereLambda(null, null, column, this, null, null); var method = _select.GetType().GetMethod("OrderBy", new[] { typeof(string), typeof(object) }); method.Invoke(_select, new object[] { descending ? $"{sql} DESC" : sql, null }); return this; } public ISelectedQuery OrderByDescending(Expression> column) => OrderByIf(true, column, true); public ISelectedQuery Where(Expression> exp) => WhereIf(true, exp); public ISelectedQuery WhereIf(bool condition, Expression> exp) { if (condition == false) return this; _lambdaParameter = exp?.Parameters[0]; var sql = _comonExp.ExpressionWhereLambda(null, null, exp, this, null, null); var method = _select.GetType().GetMethod("Where", new[] { typeof(string), typeof(object) }); method.Invoke(_select, new object[] { sql, null }); return this; } } }