mirror of
https://github.com/nsnail/FreeSql.git
synced 2025-04-22 02:32:50 +08:00
- 调整 ISelect linq to sql 和 queryable 实现依赖移至 FreeSql.Extensions.Linq;#260
This commit is contained in:
parent
98fc8baade
commit
5f98749652
@ -0,0 +1,37 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFrameworks>netstandard2.0;net45;net40</TargetFrameworks>
|
||||||
|
<Version>1.4.0-preview20200410</Version>
|
||||||
|
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||||
|
<Authors>YeXiangQin</Authors>
|
||||||
|
<Description>FreeSql 扩展包,实现 linq queryable 和 linq to sql 语法进行开发.</Description>
|
||||||
|
<PackageProjectUrl>https://github.com/2881099/FreeSql</PackageProjectUrl>
|
||||||
|
<RepositoryUrl>https://github.com/2881099/FreeSql</RepositoryUrl>
|
||||||
|
<RepositoryType>git</RepositoryType>
|
||||||
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
|
<PackageTags>FreeSql;ORM</PackageTags>
|
||||||
|
<PackageId>$(AssemblyName)</PackageId>
|
||||||
|
<PackageIcon>logo.png</PackageIcon>
|
||||||
|
<Title>$(AssemblyName)</Title>
|
||||||
|
<IsPackable>true</IsPackable>
|
||||||
|
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
|
||||||
|
<SignAssembly>true</SignAssembly>
|
||||||
|
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
|
||||||
|
<DelaySign>false</DelaySign>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="../../logo.png" Pack="true" PackagePath="\" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|netstandard2.0|AnyCPU'">
|
||||||
|
<DocumentationFile>FreeSql.Extensions.Linq.xml</DocumentationFile>
|
||||||
|
<WarningLevel>3</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\FreeSql\FreeSql.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
@ -0,0 +1,41 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<doc>
|
||||||
|
<assembly>
|
||||||
|
<name>FreeSql.Extensions.Linq</name>
|
||||||
|
</assembly>
|
||||||
|
<members>
|
||||||
|
<member name="M:FreeSqlExtensionsLinqSql.AsQueryable``1(FreeSql.ISelect{``0})">
|
||||||
|
<summary>
|
||||||
|
将 ISelect<T1> 转换为 IQueryable<T1><para></para>
|
||||||
|
此方法主要用于扩展,比如:abp IRepository GetAll() 接口方法需要返回 IQueryable 对象<para></para>
|
||||||
|
注意:IQueryable 方法污染较为严重,请尽量避免此转换
|
||||||
|
</summary>
|
||||||
|
<returns></returns>
|
||||||
|
</member>
|
||||||
|
<member name="M:FreeSqlExtensionsLinqSql.Select``2(FreeSql.ISelect{``0},System.Linq.Expressions.Expression{System.Func{``0,``1}})">
|
||||||
|
<summary>
|
||||||
|
【linq to sql】专用扩展方法,不建议直接使用
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="M:FreeSqlExtensionsLinqSql.Join``4(FreeSql.ISelect{``0},FreeSql.ISelect{``1},System.Linq.Expressions.Expression{System.Func{``0,``2}},System.Linq.Expressions.Expression{System.Func{``1,``2}},System.Linq.Expressions.Expression{System.Func{``0,``1,``3}})">
|
||||||
|
<summary>
|
||||||
|
【linq to sql】专用扩展方法,不建议直接使用
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="M:FreeSqlExtensionsLinqSql.GroupJoin``4(FreeSql.ISelect{``0},FreeSql.ISelect{``1},System.Linq.Expressions.Expression{System.Func{``0,``2}},System.Linq.Expressions.Expression{System.Func{``1,``2}},System.Linq.Expressions.Expression{System.Func{``0,FreeSql.ISelect{``1},``3}})">
|
||||||
|
<summary>
|
||||||
|
【linq to sql】专用扩展方法,不建议直接使用
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="M:FreeSqlExtensionsLinqSql.SelectMany``3(FreeSql.ISelect{``0},System.Linq.Expressions.Expression{System.Func{``0,FreeSql.ISelect{``1}}},System.Linq.Expressions.Expression{System.Func{``0,``1,``2}})">
|
||||||
|
<summary>
|
||||||
|
【linq to sql】专用扩展方法,不建议直接使用
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="M:FreeSqlExtensionsLinqSql.DefaultIfEmpty``1(FreeSql.ISelect{``0})">
|
||||||
|
<summary>
|
||||||
|
【linq to sql】专用扩展方法,不建议直接使用
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
</members>
|
||||||
|
</doc>
|
131
Extensions/FreeSql.Extensions.Linq/FreeSqlExtensionsLinq.cs
Normal file
131
Extensions/FreeSql.Extensions.Linq/FreeSqlExtensionsLinq.cs
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
using FreeSql;
|
||||||
|
using FreeSql.Extensions.Linq;
|
||||||
|
using FreeSql.Internal;
|
||||||
|
using FreeSql.Internal.CommonProvider;
|
||||||
|
using FreeSql.Internal.Model;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
public static class FreeSqlExtensionsLinqSql
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 将 ISelect<T1> 转换为 IQueryable<T1><para></para>
|
||||||
|
/// 此方法主要用于扩展,比如:abp IRepository GetAll() 接口方法需要返回 IQueryable 对象<para></para>
|
||||||
|
/// 注意:IQueryable 方法污染较为严重,请尽量避免此转换
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IQueryable<T1> AsQueryable<T1>(this ISelect<T1> that) where T1 : class
|
||||||
|
{
|
||||||
|
return new QueryableProvider<T1, T1>(that as Select1Provider<T1>);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 【linq to sql】专用扩展方法,不建议直接使用
|
||||||
|
/// </summary>
|
||||||
|
public static ISelect<TReturn> Select<T1, TReturn>(this ISelect<T1> that, Expression<Func<T1, TReturn>> select) where T1 : class where TReturn : class
|
||||||
|
{
|
||||||
|
var s1p = that as Select1Provider<T1>;
|
||||||
|
if (typeof(TReturn) == typeof(T1)) return that as ISelect<TReturn>;
|
||||||
|
s1p._tables[0].Parameter = select.Parameters[0];
|
||||||
|
s1p._selectExpression = select.Body;
|
||||||
|
if (s1p._orm.CodeFirst.IsAutoSyncStructure)
|
||||||
|
(s1p._orm.CodeFirst as CodeFirstProvider)._dicSycedTryAdd(typeof(TReturn)); //._dicSyced.TryAdd(typeof(TReturn), true);
|
||||||
|
var ret = s1p._orm.Select<TReturn>() as Select1Provider<TReturn>;
|
||||||
|
Select0Provider.CopyData(s1p, ret, null);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 【linq to sql】专用扩展方法,不建议直接使用
|
||||||
|
/// </summary>
|
||||||
|
public static ISelect<TResult> Join<T1, TInner, TKey, TResult>(this ISelect<T1> that, ISelect<TInner> inner, Expression<Func<T1, TKey>> outerKeySelector, Expression<Func<TInner, TKey>> innerKeySelector, Expression<Func<T1, TInner, TResult>> resultSelector) where T1 : class where TInner : class where TResult : class
|
||||||
|
{
|
||||||
|
var s1p = that as Select1Provider<T1>;
|
||||||
|
InternalJoin2(s1p, outerKeySelector, innerKeySelector, resultSelector);
|
||||||
|
if (typeof(TResult) == typeof(T1)) return that as ISelect<TResult>;
|
||||||
|
s1p._selectExpression = resultSelector.Body;
|
||||||
|
if (s1p._orm.CodeFirst.IsAutoSyncStructure)
|
||||||
|
(s1p._orm.CodeFirst as CodeFirstProvider)._dicSycedTryAdd(typeof(TResult)); //._dicSyced.TryAdd(typeof(TResult), true);
|
||||||
|
var ret = s1p._orm.Select<TResult>() as Select1Provider<TResult>;
|
||||||
|
Select0Provider.CopyData(s1p, ret, null);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
internal static void InternalJoin2<T1>(Select1Provider<T1> s1p, LambdaExpression outerKeySelector, LambdaExpression innerKeySelector, LambdaExpression resultSelector) where T1 : class
|
||||||
|
{
|
||||||
|
s1p._tables[0].Parameter = resultSelector.Parameters[0];
|
||||||
|
s1p._commonExpression.ExpressionLambdaToSql(outerKeySelector, new CommonExpression.ExpTSC { _tables = s1p._tables });
|
||||||
|
s1p.InternalJoin(Expression.Lambda(typeof(Func<,,>).MakeGenericType(typeof(T1), innerKeySelector.Parameters[0].Type, typeof(bool)),
|
||||||
|
Expression.Equal(outerKeySelector.Body, innerKeySelector.Body),
|
||||||
|
new[] { outerKeySelector.Parameters[0], innerKeySelector.Parameters[0] }
|
||||||
|
), SelectTableInfoType.InnerJoin);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 【linq to sql】专用扩展方法,不建议直接使用
|
||||||
|
/// </summary>
|
||||||
|
public static ISelect<TResult> GroupJoin<T1, TInner, TKey, TResult>(this ISelect<T1> that, ISelect<TInner> inner, Expression<Func<T1, TKey>> outerKeySelector, Expression<Func<TInner, TKey>> innerKeySelector, Expression<Func<T1, ISelect<TInner>, TResult>> resultSelector) where T1 : class where TInner : class where TResult : class
|
||||||
|
{
|
||||||
|
var s1p = that as Select1Provider<T1>;
|
||||||
|
InternalJoin2(s1p, outerKeySelector, innerKeySelector, resultSelector);
|
||||||
|
if (typeof(TResult) == typeof(T1)) return that as ISelect<TResult>;
|
||||||
|
s1p._selectExpression = resultSelector.Body;
|
||||||
|
if (s1p._orm.CodeFirst.IsAutoSyncStructure)
|
||||||
|
(s1p._orm.CodeFirst as CodeFirstProvider)._dicSycedTryAdd(typeof(TResult)); //._dicSyced.TryAdd(typeof(TResult), true);
|
||||||
|
var ret = s1p._orm.Select<TResult>() as Select1Provider<TResult>;
|
||||||
|
Select0Provider.CopyData(s1p, ret, null);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 【linq to sql】专用扩展方法,不建议直接使用
|
||||||
|
/// </summary>
|
||||||
|
public static ISelect<TResult> SelectMany<T1, TCollection, TResult>(this ISelect<T1> that, Expression<Func<T1, ISelect<TCollection>>> collectionSelector, Expression<Func<T1, TCollection, TResult>> resultSelector) where T1 : class where TCollection : class where TResult : class
|
||||||
|
{
|
||||||
|
var s1p = that as Select1Provider<T1>;
|
||||||
|
InternalSelectMany2(s1p, collectionSelector, resultSelector);
|
||||||
|
if (typeof(TResult) == typeof(T1)) return that as ISelect<TResult>;
|
||||||
|
s1p._selectExpression = resultSelector.Body;
|
||||||
|
if (s1p._orm.CodeFirst.IsAutoSyncStructure)
|
||||||
|
(s1p._orm.CodeFirst as CodeFirstProvider)._dicSycedTryAdd(typeof(TResult)); //._dicSyced.TryAdd(typeof(TResult), true);
|
||||||
|
var ret = s1p._orm.Select<TResult>() as Select1Provider<TResult>;
|
||||||
|
Select0Provider.CopyData(s1p, ret, null);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
internal static void InternalSelectMany2<T1>(Select1Provider<T1> s1p, LambdaExpression collectionSelector, LambdaExpression resultSelector) where T1 : class
|
||||||
|
{
|
||||||
|
SelectTableInfo find = null;
|
||||||
|
if (collectionSelector.Body.NodeType == ExpressionType.Call)
|
||||||
|
{
|
||||||
|
var callExp = collectionSelector.Body as MethodCallExpression;
|
||||||
|
if (callExp.Method.Name == "DefaultIfEmpty" && callExp.Method.GetGenericArguments().Any())
|
||||||
|
{
|
||||||
|
find = s1p._tables.Where((a, idx) => idx > 0 && a.Type == SelectTableInfoType.InnerJoin && a.Table.Type == callExp.Method.GetGenericArguments()[0]).LastOrDefault();
|
||||||
|
if (find != null)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(find.On)) find.On = Regex.Replace(find.On, $@"\b{find.Alias}\.", $"{resultSelector.Parameters[1].Name}.");
|
||||||
|
if (!string.IsNullOrEmpty(find.NavigateCondition)) find.NavigateCondition = Regex.Replace(find.NavigateCondition, $@"\b{find.Alias}\.", $"{resultSelector.Parameters[1].Name}.");
|
||||||
|
find.Type = SelectTableInfoType.LeftJoin;
|
||||||
|
find.Alias = resultSelector.Parameters[1].Name;
|
||||||
|
find.Parameter = resultSelector.Parameters[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (find == null)
|
||||||
|
{
|
||||||
|
var tb = s1p._commonUtils.GetTableByEntity(resultSelector.Parameters[1].Type);
|
||||||
|
if (tb == null) throw new Exception($"SelectMany 错误的类型:{resultSelector.Parameters[1].Type.FullName}");
|
||||||
|
s1p._tables.Add(new SelectTableInfo { Alias = resultSelector.Parameters[1].Name, AliasInit = resultSelector.Parameters[1].Name, Parameter = resultSelector.Parameters[1], Table = tb, Type = SelectTableInfoType.From });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 【linq to sql】专用扩展方法,不建议直接使用
|
||||||
|
/// </summary>
|
||||||
|
public static ISelect<T1> DefaultIfEmpty<T1>(this ISelect<T1> that) where T1 : class
|
||||||
|
{
|
||||||
|
return that;
|
||||||
|
}
|
||||||
|
}
|
279
Extensions/FreeSql.Extensions.Linq/QueryableProvider.cs
Normal file
279
Extensions/FreeSql.Extensions.Linq/QueryableProvider.cs
Normal file
@ -0,0 +1,279 @@
|
|||||||
|
using FreeSql.Internal;
|
||||||
|
using FreeSql.Internal.CommonProvider;
|
||||||
|
using FreeSql.Internal.Model;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace FreeSql.Extensions.Linq
|
||||||
|
{
|
||||||
|
class QueryableProvider<TCurrent, TSource> : IQueryable<TCurrent>, IOrderedQueryable<TCurrent> where TSource : class
|
||||||
|
{
|
||||||
|
private Expression _expression;
|
||||||
|
private IQueryProvider _provider;
|
||||||
|
private Select1Provider<TSource> _select;
|
||||||
|
|
||||||
|
public QueryableProvider(Select1Provider<TSource> select)
|
||||||
|
{
|
||||||
|
_select = select;
|
||||||
|
_expression = Expression.Constant(this);
|
||||||
|
_provider = new QueryProvider<TCurrent, TSource>(_select);
|
||||||
|
}
|
||||||
|
public QueryableProvider(Expression expression, IQueryProvider provider, Select1Provider<TSource> select)
|
||||||
|
{
|
||||||
|
_select = select;
|
||||||
|
_expression = expression;
|
||||||
|
_provider = provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerator<TCurrent> GetEnumerator()
|
||||||
|
{
|
||||||
|
var result = _provider.Execute<List<TCurrent>>(_expression);
|
||||||
|
if (result == null)
|
||||||
|
yield break;
|
||||||
|
foreach (var item in result)
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();
|
||||||
|
|
||||||
|
public Type ElementType => typeof(QueryableProvider<TCurrent, TSource>);
|
||||||
|
public Expression Expression => _expression;
|
||||||
|
public IQueryProvider Provider => _provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
class QueryProvider<TCurrent, TSource> : IQueryProvider where TSource : class
|
||||||
|
{
|
||||||
|
private Select1Provider<TSource> _select;
|
||||||
|
|
||||||
|
public QueryProvider(Select1Provider<TSource> select)
|
||||||
|
{
|
||||||
|
_select = select;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
|
||||||
|
{
|
||||||
|
if (typeof(TElement) != typeof(TCurrent))
|
||||||
|
return new QueryableProvider<TElement, TSource>(expression, new QueryProvider<TElement, TSource>(_select), _select);
|
||||||
|
|
||||||
|
return new QueryableProvider<TElement, TSource>(expression, this, _select);
|
||||||
|
}
|
||||||
|
public IQueryable CreateQuery(Expression expression) => throw new NotImplementedException();
|
||||||
|
|
||||||
|
public TResult Execute<TResult>(Expression expression)
|
||||||
|
{
|
||||||
|
var stackCallExps = new Stack<MethodCallExpression>();
|
||||||
|
var callExp = expression as MethodCallExpression;
|
||||||
|
while(callExp != null)
|
||||||
|
{
|
||||||
|
stackCallExps.Push(callExp);
|
||||||
|
callExp = callExp?.Arguments.FirstOrDefault() as MethodCallExpression;
|
||||||
|
}
|
||||||
|
|
||||||
|
SelectGroupingProvider groupBy = null;
|
||||||
|
var isfirst = false;
|
||||||
|
while (stackCallExps.Any())
|
||||||
|
{
|
||||||
|
callExp = stackCallExps.Pop();
|
||||||
|
TResult throwCallExp(string message) => throw new Exception($"FreeSql Queryable 解析出错,执行的方法 {callExp.Method.Name} {message}");
|
||||||
|
if (callExp.Method.DeclaringType != typeof(Queryable)) return throwCallExp($"必须属于 System.Linq.Enumerable");
|
||||||
|
|
||||||
|
TResult tplMaxMinAvgSum(string method) {
|
||||||
|
if (callExp.Arguments.Count == 2)
|
||||||
|
{
|
||||||
|
var avgParam = (callExp.Arguments[1] as UnaryExpression)?.Operand as LambdaExpression;
|
||||||
|
return (TResult)Utils.GetDataReaderValue(typeof(TResult),
|
||||||
|
_select.GetType().GetMethod(method).MakeGenericMethod(avgParam.ReturnType).Invoke(_select, new object[] { avgParam }));
|
||||||
|
}
|
||||||
|
return throwCallExp($" 不支持 {callExp.Arguments.Count}个参数的方法");
|
||||||
|
}
|
||||||
|
TResult tplOrderBy(string method, bool isDescending)
|
||||||
|
{
|
||||||
|
if (callExp.Arguments.Count == 2)
|
||||||
|
{
|
||||||
|
var arg1 = (callExp.Arguments[1] as UnaryExpression)?.Operand as LambdaExpression;
|
||||||
|
_select.OrderByReflection(arg1, isDescending);
|
||||||
|
return default(TResult);
|
||||||
|
}
|
||||||
|
return throwCallExp($" 不支持 {callExp.Arguments.Count}个参数的方法");
|
||||||
|
}
|
||||||
|
switch (callExp.Method.Name)
|
||||||
|
{
|
||||||
|
case "Any":
|
||||||
|
if (callExp.Arguments.Count == 2) _select.Where((Expression<Func<TSource, bool>>)(callExp.Arguments[1] as UnaryExpression)?.Operand);
|
||||||
|
return (TResult)(object)_select.Any();
|
||||||
|
case "AsQueryable":
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Max": return tplMaxMinAvgSum("Max");
|
||||||
|
case "Min": return tplMaxMinAvgSum("Min");
|
||||||
|
case "Sum": return tplMaxMinAvgSum("Sum");
|
||||||
|
case "Average": return tplMaxMinAvgSum("Avg");
|
||||||
|
|
||||||
|
case "Concat":
|
||||||
|
return throwCallExp(" 不支持");
|
||||||
|
case "Contains":
|
||||||
|
if (callExp.Arguments.Count == 2)
|
||||||
|
{
|
||||||
|
var dywhere = (callExp.Arguments[1] as ConstantExpression)?.Value as TSource;
|
||||||
|
if (dywhere == null) return throwCallExp($" 参数值不能为 null");
|
||||||
|
_select.WhereDynamic(dywhere);
|
||||||
|
return (TResult)(object)_select.Any();
|
||||||
|
}
|
||||||
|
return throwCallExp($" 不支持 {callExp.Arguments.Count}个参数的方法");
|
||||||
|
case "Count":
|
||||||
|
if (callExp.Arguments.Count == 2) _select.Where((Expression<Func<TSource, bool>>)(callExp.Arguments[1] as UnaryExpression)?.Operand);
|
||||||
|
return (TResult)Utils.GetDataReaderValue(typeof(TResult), _select.Count());
|
||||||
|
|
||||||
|
case "Distinct":
|
||||||
|
if (callExp.Arguments.Count == 1)
|
||||||
|
{
|
||||||
|
_select.Distinct();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return throwCallExp(" 不支持");
|
||||||
|
|
||||||
|
case "ElementAt":
|
||||||
|
case "ElementAtOrDefault":
|
||||||
|
_select.Offset((int)(callExp.Arguments[1] as ConstantExpression)?.Value);
|
||||||
|
_select.Limit(1);
|
||||||
|
isfirst = true;
|
||||||
|
break;
|
||||||
|
case "First":
|
||||||
|
case "FirstOrDefault":
|
||||||
|
case "Single":
|
||||||
|
case "SingleOrDefault":
|
||||||
|
if (callExp.Arguments.Count == 2) _select.Where((Expression<Func<TSource, bool>>)(callExp.Arguments[1] as UnaryExpression)?.Operand);
|
||||||
|
_select.Limit(1);
|
||||||
|
isfirst = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "OrderBy":
|
||||||
|
tplOrderBy("OrderByReflection", false);
|
||||||
|
break;
|
||||||
|
case "OrderByDescending":
|
||||||
|
tplOrderBy("OrderByReflection", true);
|
||||||
|
break;
|
||||||
|
case "ThenBy":
|
||||||
|
tplOrderBy("OrderByReflection", false);
|
||||||
|
break;
|
||||||
|
case "ThenByDescending":
|
||||||
|
tplOrderBy("OrderByReflection", true);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Where":
|
||||||
|
var whereParam = (callExp.Arguments[1] as UnaryExpression)?.Operand as LambdaExpression;
|
||||||
|
if (whereParam.Parameters.Count == 1)
|
||||||
|
{
|
||||||
|
if (groupBy != null) groupBy.InternalHaving(whereParam);
|
||||||
|
else _select.InternalWhere(whereParam);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return throwCallExp(" 不支持");
|
||||||
|
|
||||||
|
case "Skip":
|
||||||
|
_select.Offset((int)(callExp.Arguments[1] as ConstantExpression)?.Value);
|
||||||
|
break;
|
||||||
|
case "Take":
|
||||||
|
_select.Limit((int)(callExp.Arguments[1] as ConstantExpression)?.Value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "ToList":
|
||||||
|
if (callExp.Arguments.Count == 1)
|
||||||
|
return (TResult)(object)_select.ToList();
|
||||||
|
return throwCallExp(" 不支持");
|
||||||
|
|
||||||
|
|
||||||
|
case "Select":
|
||||||
|
var selectParam = (callExp.Arguments[1] as UnaryExpression)?.Operand as LambdaExpression;
|
||||||
|
if (selectParam.Parameters.Count == 1)
|
||||||
|
{
|
||||||
|
_select._selectExpression = selectParam;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return throwCallExp(" 不支持");
|
||||||
|
|
||||||
|
case "Join":
|
||||||
|
if (callExp.Arguments.Count == 5)
|
||||||
|
{
|
||||||
|
var arg2 = (callExp.Arguments[2] as UnaryExpression)?.Operand as LambdaExpression;
|
||||||
|
var arg3 = (callExp.Arguments[3] as UnaryExpression)?.Operand as LambdaExpression;
|
||||||
|
var arg4 = (callExp.Arguments[4] as UnaryExpression)?.Operand as LambdaExpression;
|
||||||
|
FreeSqlExtensionsLinqSql.InternalJoin2(_select, arg2, arg3, arg4);
|
||||||
|
_select._selectExpression = arg4.Body;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return throwCallExp($" 不支持 {callExp.Arguments.Count}个参数的方法");
|
||||||
|
|
||||||
|
case "GroupJoin":
|
||||||
|
if (callExp.Arguments.Count == 5)
|
||||||
|
{
|
||||||
|
var arg2 = (callExp.Arguments[2] as UnaryExpression)?.Operand as LambdaExpression;
|
||||||
|
var arg3 = (callExp.Arguments[3] as UnaryExpression)?.Operand as LambdaExpression;
|
||||||
|
var arg4 = (callExp.Arguments[4] as UnaryExpression)?.Operand as LambdaExpression;
|
||||||
|
FreeSqlExtensionsLinqSql.InternalJoin2(_select, arg2, arg3, arg4);
|
||||||
|
_select._selectExpression = arg4.Body;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return throwCallExp($" 不支持 {callExp.Arguments.Count}个参数的方法");
|
||||||
|
|
||||||
|
case "SelectMany":
|
||||||
|
if (callExp.Arguments.Count == 3)
|
||||||
|
{
|
||||||
|
var arg1 = (callExp.Arguments[1] as UnaryExpression)?.Operand as LambdaExpression;
|
||||||
|
var arg2 = (callExp.Arguments[2] as UnaryExpression)?.Operand as LambdaExpression;
|
||||||
|
FreeSqlExtensionsLinqSql.InternalSelectMany2(_select, arg1, arg2);
|
||||||
|
_select._selectExpression = arg2.Body;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return throwCallExp($" 不支持 {callExp.Arguments.Count}个参数的方法");
|
||||||
|
|
||||||
|
case "DefaultIfEmpty":
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Last":
|
||||||
|
case "LastOrDefault":
|
||||||
|
return throwCallExp(" 不支持");
|
||||||
|
|
||||||
|
case "GroupBy":
|
||||||
|
return throwCallExp(" 不支持");
|
||||||
|
|
||||||
|
if (callExp.Arguments.Count == 2) //TODO: 待实现
|
||||||
|
{
|
||||||
|
var arg1 = (callExp.Arguments[1] as UnaryExpression)?.Operand as LambdaExpression;
|
||||||
|
|
||||||
|
var map = new ReadAnonymousTypeInfo();
|
||||||
|
var field = new StringBuilder();
|
||||||
|
var index = -10000; //临时规则,不返回 as1
|
||||||
|
|
||||||
|
_select._commonExpression.ReadAnonymousField(_select._tables, field, map, ref index, arg1, null, _select._whereCascadeExpression, false); //不走 DTO 映射
|
||||||
|
var sql = field.ToString();
|
||||||
|
_select.GroupBy(sql.Length > 0 ? sql.Substring(2) : null);
|
||||||
|
groupBy = new SelectGroupingProvider(_select._orm, _select, map, sql, _select._commonExpression, _select._tables);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return throwCallExp($" 不支持 {callExp.Arguments.Count}个参数的方法");
|
||||||
|
|
||||||
|
default:
|
||||||
|
return throwCallExp(" 不支持");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isfirst)
|
||||||
|
{
|
||||||
|
_select.Limit(1);
|
||||||
|
if (_select._selectExpression != null)
|
||||||
|
return (TResult)(object)_select.InternalToList<TCurrent>(_select._selectExpression).FirstOrDefault();
|
||||||
|
return (TResult)(object)_select.ToList().FirstOrDefault();
|
||||||
|
}
|
||||||
|
if (_select._selectExpression != null)
|
||||||
|
return (TResult)(object)_select.InternalToList<TCurrent>(_select._selectExpression);
|
||||||
|
return (TResult)(object)_select.ToList();
|
||||||
|
}
|
||||||
|
public object Execute(Expression expression) => throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
BIN
Extensions/FreeSql.Extensions.Linq/key.snk
Normal file
BIN
Extensions/FreeSql.Extensions.Linq/key.snk
Normal file
Binary file not shown.
@ -73,7 +73,7 @@ namespace FreeSql
|
|||||||
public ISelect<TEntity> Where(Expression<Func<TEntity, bool>> exp) => _dbset.OrmSelectInternal(null).Where(exp);
|
public ISelect<TEntity> Where(Expression<Func<TEntity, bool>> exp) => _dbset.OrmSelectInternal(null).Where(exp);
|
||||||
public ISelect<TEntity> WhereIf(bool condition, Expression<Func<TEntity, bool>> exp) => _dbset.OrmSelectInternal(null).WhereIf(condition, exp);
|
public ISelect<TEntity> WhereIf(bool condition, Expression<Func<TEntity, bool>> exp) => _dbset.OrmSelectInternal(null).WhereIf(condition, exp);
|
||||||
|
|
||||||
public int Delete(Expression<Func<TEntity, bool>> predicate)
|
public virtual int Delete(Expression<Func<TEntity, bool>> predicate)
|
||||||
{
|
{
|
||||||
var delete = _dbset.OrmDeleteInternal(null).Where(predicate);
|
var delete = _dbset.OrmDeleteInternal(null).Where(predicate);
|
||||||
var sql = delete.ToSql();
|
var sql = delete.ToSql();
|
||||||
@ -82,12 +82,12 @@ namespace FreeSql
|
|||||||
return affrows;
|
return affrows;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Delete(TEntity entity)
|
public virtual int Delete(TEntity entity)
|
||||||
{
|
{
|
||||||
_dbset.Remove(entity);
|
_dbset.Remove(entity);
|
||||||
return _db.SaveChanges();
|
return _db.SaveChanges();
|
||||||
}
|
}
|
||||||
public int Delete(IEnumerable<TEntity> entitys)
|
public virtual int Delete(IEnumerable<TEntity> entitys)
|
||||||
{
|
{
|
||||||
_dbset.RemoveRange(entitys);
|
_dbset.RemoveRange(entitys);
|
||||||
return _db.SaveChanges();
|
return _db.SaveChanges();
|
||||||
@ -157,7 +157,7 @@ namespace FreeSql
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Delete(TKey id) => Delete(CheckTKeyAndReturnIdEntity(id));
|
public virtual int Delete(TKey id) => Delete(CheckTKeyAndReturnIdEntity(id));
|
||||||
public TEntity Find(TKey id) => _dbset.OrmSelectInternal(CheckTKeyAndReturnIdEntity(id)).ToOne();
|
public TEntity Find(TKey id) => _dbset.OrmSelectInternal(CheckTKeyAndReturnIdEntity(id)).ToOne();
|
||||||
public TEntity Get(TKey id) => Find(id);
|
public TEntity Get(TKey id) => Find(id);
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ namespace FreeSql
|
|||||||
where TEntity : class
|
where TEntity : class
|
||||||
{
|
{
|
||||||
|
|
||||||
async public Task<int> DeleteAsync(Expression<Func<TEntity, bool>> predicate)
|
async virtual public Task<int> DeleteAsync(Expression<Func<TEntity, bool>> predicate)
|
||||||
{
|
{
|
||||||
var delete = _dbset.OrmDeleteInternal(null).Where(predicate);
|
var delete = _dbset.OrmDeleteInternal(null).Where(predicate);
|
||||||
var sql = delete.ToSql();
|
var sql = delete.ToSql();
|
||||||
@ -22,12 +22,12 @@ namespace FreeSql
|
|||||||
return affrows;
|
return affrows;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<int> DeleteAsync(TEntity entity)
|
public virtual Task<int> DeleteAsync(TEntity entity)
|
||||||
{
|
{
|
||||||
_dbset.Remove(entity);
|
_dbset.Remove(entity);
|
||||||
return _db.SaveChangesAsync();
|
return _db.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
public Task<int> DeleteAsync(IEnumerable<TEntity> entitys)
|
public virtual Task<int> DeleteAsync(IEnumerable<TEntity> entitys)
|
||||||
{
|
{
|
||||||
_dbset.RemoveRange(entitys);
|
_dbset.RemoveRange(entitys);
|
||||||
return _db.SaveChangesAsync();
|
return _db.SaveChangesAsync();
|
||||||
@ -73,7 +73,7 @@ namespace FreeSql
|
|||||||
|
|
||||||
partial class BaseRepository<TEntity, TKey>
|
partial class BaseRepository<TEntity, TKey>
|
||||||
{
|
{
|
||||||
public Task<int> DeleteAsync(TKey id) => DeleteAsync(CheckTKeyAndReturnIdEntity(id));
|
public virtual Task<int> DeleteAsync(TKey id) => DeleteAsync(CheckTKeyAndReturnIdEntity(id));
|
||||||
public Task<TEntity> FindAsync(TKey id) => _dbset.OrmSelectInternal(CheckTKeyAndReturnIdEntity(id)).ToOneAsync();
|
public Task<TEntity> FindAsync(TKey id) => _dbset.OrmSelectInternal(CheckTKeyAndReturnIdEntity(id)).ToOneAsync();
|
||||||
public Task<TEntity> GetAsync(TKey id) => FindAsync(id);
|
public Task<TEntity> GetAsync(TKey id) => FindAsync(id);
|
||||||
}
|
}
|
||||||
|
@ -563,8 +563,6 @@ WHERE ROWNUM < 11";
|
|||||||
.UpdateColumns(x => new { x.Status, x.CategoryId, x.ArticleTitle })
|
.UpdateColumns(x => new { x.Status, x.CategoryId, x.ArticleTitle })
|
||||||
.ToSql();
|
.ToSql();
|
||||||
|
|
||||||
var sqldddklist = g.mysql.Select<NewsArticle>().Select(a => new NewsArticleDto { }).ToList();
|
|
||||||
|
|
||||||
|
|
||||||
var sql1111333 = g.mysql.Update<Model2>()
|
var sql1111333 = g.mysql.Update<Model2>()
|
||||||
.SetSource(new Model2 { id = 1, Title = "xxx", Parent_id = 0 })
|
.SetSource(new Model2 { id = 1, Title = "xxx", Parent_id = 0 })
|
||||||
@ -608,15 +606,6 @@ WHERE ROWNUM < 11";
|
|||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
var ttt1 = g.mysql.Select<Model1>().Where(a => a.Childs.AsSelect().Any(b => b.Title == "111")).ToList();
|
var ttt1 = g.mysql.Select<Model1>().Where(a => a.Childs.AsSelect().Any(b => b.Title == "111")).ToList();
|
||||||
|
|
||||||
var linqto1 =
|
|
||||||
from p in g.mysql.Select<Order>()
|
|
||||||
where p.Id >= 0
|
|
||||||
// && p.OrderDetails.AsSelect().Where(c => c.Id > 10).Any()
|
|
||||||
orderby p.Id descending
|
|
||||||
orderby p.CustomerName ascending
|
|
||||||
select new { Name = p.CustomerName, Length = p.Id };
|
|
||||||
|
|
||||||
var testpid1 = g.mysql.Insert<TestTypeInfo>().AppendData(new TestTypeInfo { Name = "Name" + DateTime.Now.ToString("yyyyMMddHHmmss") }).ExecuteIdentity();
|
var testpid1 = g.mysql.Insert<TestTypeInfo>().AppendData(new TestTypeInfo { Name = "Name" + DateTime.Now.ToString("yyyyMMddHHmmss") }).ExecuteIdentity();
|
||||||
g.mysql.Insert<TestInfo>().AppendData(new TestInfo { Title = "Title" + DateTime.Now.ToString("yyyyMMddHHmmss"), CreateTime = DateTime.Now, TypeGuid = (int)testpid1 }).ExecuteAffrows();
|
g.mysql.Insert<TestInfo>().AppendData(new TestInfo { Title = "Title" + DateTime.Now.ToString("yyyyMMddHHmmss"), CreateTime = DateTime.Now, TypeGuid = (int)testpid1 }).ExecuteAffrows();
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\Extensions\FreeSql.Extensions.LazyLoading\FreeSql.Extensions.LazyLoading.csproj" />
|
<ProjectReference Include="..\..\Extensions\FreeSql.Extensions.LazyLoading\FreeSql.Extensions.LazyLoading.csproj" />
|
||||||
|
<ProjectReference Include="..\..\Extensions\FreeSql.Extensions.Linq\FreeSql.Extensions.Linq.csproj" />
|
||||||
<ProjectReference Include="..\..\FreeSql.DbContext\FreeSql.DbContext.csproj" />
|
<ProjectReference Include="..\..\FreeSql.DbContext\FreeSql.DbContext.csproj" />
|
||||||
<ProjectReference Include="..\..\FreeSql\FreeSql.csproj" />
|
<ProjectReference Include="..\..\FreeSql\FreeSql.csproj" />
|
||||||
<ProjectReference Include="..\..\Providers\FreeSql.Provider.MsAccess\FreeSql.Provider.MsAccess.csproj" />
|
<ProjectReference Include="..\..\Providers\FreeSql.Provider.MsAccess\FreeSql.Provider.MsAccess.csproj" />
|
||||||
|
202
FreeSql.Tests/FreeSql.Tests/Queryable/QueryableLinqToSqlTests.cs
Normal file
202
FreeSql.Tests/FreeSql.Tests/Queryable/QueryableLinqToSqlTests.cs
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
using FreeSql.DataAnnotations;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace FreeSql.Tests.Linq
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
class TestQueryableLinqToSql
|
||||||
|
{
|
||||||
|
public Guid id { get; set; }
|
||||||
|
|
||||||
|
public string name { get; set; }
|
||||||
|
|
||||||
|
public int click { get; set; } = 10;
|
||||||
|
|
||||||
|
public DateTime createtime { get; set; } = DateTime.Now;
|
||||||
|
}
|
||||||
|
class TestQueryableLinqToSqlComment
|
||||||
|
{
|
||||||
|
public Guid id { get; set; }
|
||||||
|
|
||||||
|
public Guid TestLinqToSqlId { get; set; }
|
||||||
|
public TestQueryableLinqToSql TEstLinqToSql { get; set; }
|
||||||
|
|
||||||
|
public string text { get; set; }
|
||||||
|
|
||||||
|
public DateTime createtime { get; set; } = DateTime.Now;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class QueryableLinqToSqlTests
|
||||||
|
{
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Where()
|
||||||
|
{
|
||||||
|
var item = new TestQueryableLinqToSql { name = Guid.NewGuid().ToString() };
|
||||||
|
g.sqlite.Insert<TestQueryableLinqToSql>().AppendData(item).ExecuteAffrows();
|
||||||
|
|
||||||
|
var t1 = (from a in g.sqlite.Select<TestQueryableLinqToSql>().AsQueryable()
|
||||||
|
where a.id == item.id
|
||||||
|
select a).ToList();
|
||||||
|
Assert.True(t1.Any());
|
||||||
|
Assert.Equal(item.id, t1[0].id);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Select()
|
||||||
|
{
|
||||||
|
var item = new TestQueryableLinqToSql { name = Guid.NewGuid().ToString() };
|
||||||
|
g.sqlite.Insert<TestQueryableLinqToSql>().AppendData(item).ExecuteAffrows();
|
||||||
|
|
||||||
|
var t1 = (from a in g.sqlite.Select<TestQueryableLinqToSql>().AsQueryable()
|
||||||
|
where a.id == item.id
|
||||||
|
select new { a.id }).ToList();
|
||||||
|
Assert.True(t1.Any());
|
||||||
|
Assert.Equal(item.id, t1[0].id);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GroupBy()
|
||||||
|
{
|
||||||
|
//var item = new TestQueryableLinqToSql { name = Guid.NewGuid().ToString() };
|
||||||
|
//g.sqlite.Insert<TestQueryableLinqToSql>().AppendData(item).ExecuteAffrows();
|
||||||
|
|
||||||
|
//var t1 = (from a in g.sqlite.Select<TestQueryableLinqToSql>().AsQueryable()
|
||||||
|
// where a.id == item.id
|
||||||
|
// group a by new { a.id, a.name } into g
|
||||||
|
// select new
|
||||||
|
// {
|
||||||
|
// g.Key.id,
|
||||||
|
// g.Key.name,
|
||||||
|
// cou = g.Count(),
|
||||||
|
// avg = g.Average(x => x.click),
|
||||||
|
// sum = g.Sum(x => x.click),
|
||||||
|
// max = g.Max(x => x.click),
|
||||||
|
// min = g.Min(x => x.click)
|
||||||
|
// }).ToList();
|
||||||
|
//Assert.True(t1.Any());
|
||||||
|
//Assert.Equal(item.id, t1.First().id);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CaseWhen()
|
||||||
|
{
|
||||||
|
var item = new TestQueryableLinqToSql { name = Guid.NewGuid().ToString() };
|
||||||
|
g.sqlite.Insert<TestQueryableLinqToSql>().AppendData(item).ExecuteAffrows();
|
||||||
|
|
||||||
|
var t1 = (from a in g.sqlite.Select<TestQueryableLinqToSql>().AsQueryable()
|
||||||
|
where a.id == item.id
|
||||||
|
select new
|
||||||
|
{
|
||||||
|
a.id,
|
||||||
|
a.name,
|
||||||
|
testsub = new
|
||||||
|
{
|
||||||
|
time = a.click > 10 ? "大于" : "小于或等于"
|
||||||
|
}
|
||||||
|
}).ToList();
|
||||||
|
Assert.True(t1.Any());
|
||||||
|
Assert.Equal(item.id, t1[0].id);
|
||||||
|
Assert.Equal("小于或等于", t1[0].testsub.time);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Join()
|
||||||
|
{
|
||||||
|
var item = new TestQueryableLinqToSql { name = Guid.NewGuid().ToString() };
|
||||||
|
g.sqlite.Insert<TestQueryableLinqToSql>().AppendData(item).ExecuteAffrows();
|
||||||
|
var comment = new TestQueryableLinqToSqlComment { TestLinqToSqlId = item.id, text = Guid.NewGuid().ToString() };
|
||||||
|
g.sqlite.Insert<TestQueryableLinqToSqlComment>().AppendData(comment).ExecuteAffrows();
|
||||||
|
|
||||||
|
var t1 = (from a in g.sqlite.Select<TestQueryableLinqToSql>().AsQueryable()
|
||||||
|
join b in g.sqlite.Select<TestQueryableLinqToSqlComment>().AsQueryable() on a.id equals b.TestLinqToSqlId
|
||||||
|
select a).ToList();
|
||||||
|
Assert.True(t1.Any());
|
||||||
|
//Assert.Equal(item.id, t1[0].id);
|
||||||
|
|
||||||
|
var t2 = (from a in g.sqlite.Select<TestQueryableLinqToSql>().AsQueryable()
|
||||||
|
join b in g.sqlite.Select<TestQueryableLinqToSqlComment>().AsQueryable() on a.id equals b.TestLinqToSqlId
|
||||||
|
select new { a.id, bid = b.id }).ToList();
|
||||||
|
Assert.True(t2.Any());
|
||||||
|
//Assert.Equal(item.id, t2[0].id);
|
||||||
|
//Assert.Equal(comment.id, t2[0].bid);
|
||||||
|
|
||||||
|
var t3 = (from a in g.sqlite.Select<TestQueryableLinqToSql>().AsQueryable()
|
||||||
|
join b in g.sqlite.Select<TestQueryableLinqToSqlComment>().AsQueryable() on a.id equals b.TestLinqToSqlId
|
||||||
|
where a.id == item.id
|
||||||
|
select new { a.id, bid = b.id }).ToList();
|
||||||
|
Assert.True(t3.Any());
|
||||||
|
Assert.Equal(item.id, t3[0].id);
|
||||||
|
Assert.Equal(comment.id, t3[0].bid);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void LeftJoin()
|
||||||
|
{
|
||||||
|
var item = new TestQueryableLinqToSql { name = Guid.NewGuid().ToString() };
|
||||||
|
g.sqlite.Insert<TestQueryableLinqToSql>().AppendData(item).ExecuteAffrows();
|
||||||
|
var comment = new TestQueryableLinqToSqlComment { TestLinqToSqlId = item.id, text = Guid.NewGuid().ToString() };
|
||||||
|
g.sqlite.Insert<TestQueryableLinqToSqlComment>().AppendData(comment).ExecuteAffrows();
|
||||||
|
|
||||||
|
var t1 = (from a in g.sqlite.Select<TestQueryableLinqToSql>().AsQueryable()
|
||||||
|
join b in g.sqlite.Select<TestQueryableLinqToSqlComment>().AsQueryable() on a.id equals b.TestLinqToSqlId into temp
|
||||||
|
from tc in temp.DefaultIfEmpty()
|
||||||
|
select a).ToList();
|
||||||
|
Assert.True(t1.Any());
|
||||||
|
//Assert.Equal(item.id, t1[0].id);
|
||||||
|
|
||||||
|
var t2 = (from a in g.sqlite.Select<TestQueryableLinqToSql>().AsQueryable()
|
||||||
|
join b in g.sqlite.Select<TestQueryableLinqToSqlComment>().AsQueryable() on a.id equals b.TestLinqToSqlId into temp
|
||||||
|
from tc in temp.DefaultIfEmpty()
|
||||||
|
select new { a.id, bid = tc.id }).ToList();
|
||||||
|
Assert.True(t2.Any());
|
||||||
|
//Assert.Equal(item.id, t2[0].id);
|
||||||
|
//Assert.Equal(comment.id, t2[0].bid);
|
||||||
|
|
||||||
|
var t3 = (from a in g.sqlite.Select<TestQueryableLinqToSql>().AsQueryable()
|
||||||
|
join b in g.sqlite.Select<TestQueryableLinqToSqlComment>().AsQueryable() on a.id equals b.TestLinqToSqlId into temp
|
||||||
|
from tc in temp.DefaultIfEmpty()
|
||||||
|
where a.id == item.id
|
||||||
|
select new { a.id, bid = tc.id }).ToList();
|
||||||
|
Assert.True(t3.Any());
|
||||||
|
Assert.Equal(item.id, t3[0].id);
|
||||||
|
Assert.Equal(comment.id, t3[0].bid);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void From()
|
||||||
|
{
|
||||||
|
var item = new TestQueryableLinqToSql { name = Guid.NewGuid().ToString() };
|
||||||
|
g.sqlite.Insert<TestQueryableLinqToSql>().AppendData(item).ExecuteAffrows();
|
||||||
|
var comment = new TestQueryableLinqToSqlComment { TestLinqToSqlId = item.id, text = Guid.NewGuid().ToString() };
|
||||||
|
g.sqlite.Insert<TestQueryableLinqToSqlComment>().AppendData(comment).ExecuteAffrows();
|
||||||
|
|
||||||
|
var t1 = (from a in g.sqlite.Select<TestQueryableLinqToSql>().AsQueryable()
|
||||||
|
from b in g.sqlite.Select<TestQueryableLinqToSqlComment>().AsQueryable()
|
||||||
|
where a.id == b.TestLinqToSqlId
|
||||||
|
select a).ToList();
|
||||||
|
Assert.True(t1.Any());
|
||||||
|
//Assert.Equal(item.id, t1[0].id);
|
||||||
|
|
||||||
|
var t2 = (from a in g.sqlite.Select<TestQueryableLinqToSql>().AsQueryable()
|
||||||
|
from b in g.sqlite.Select<TestQueryableLinqToSqlComment>().AsQueryable()
|
||||||
|
where a.id == b.TestLinqToSqlId
|
||||||
|
select new { a.id, bid = b.id }).ToList();
|
||||||
|
Assert.True(t2.Any());
|
||||||
|
//Assert.Equal(item.id, t2[0].id);
|
||||||
|
//Assert.Equal(comment.id, t2[0].bid);
|
||||||
|
|
||||||
|
var t3 = (from a in g.sqlite.Select<TestQueryableLinqToSql>().AsQueryable()
|
||||||
|
from b in g.sqlite.Select<TestQueryableLinqToSqlComment>().AsQueryable()
|
||||||
|
where a.id == b.TestLinqToSqlId
|
||||||
|
where a.id == item.id
|
||||||
|
select new { a.id, bid = b.id }).ToList();
|
||||||
|
Assert.True(t3.Any());
|
||||||
|
Assert.Equal(item.id, t3[0].id);
|
||||||
|
Assert.Equal(comment.id, t3[0].bid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -17,7 +17,7 @@ using System.Diagnostics;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace FreeSql.Tests
|
namespace FreeSql.Tests.Linq
|
||||||
{
|
{
|
||||||
public class QueryableTest
|
public class QueryableTest
|
||||||
{
|
{
|
||||||
@ -66,6 +66,126 @@ namespace FreeSql.Tests
|
|||||||
Assert.True(fsql.Select<qt01>().AsQueryable().Any(a => a.id == sd[0].id));
|
Assert.True(fsql.Select<qt01>().AsQueryable().Any(a => a.id == sd[0].id));
|
||||||
Assert.False(fsql.Select<qt01>().AsQueryable().Any(a => a.id == sd[0].id && sd[0].id == 0));
|
Assert.False(fsql.Select<qt01>().AsQueryable().Any(a => a.id == sd[0].id && sd[0].id == 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Max()
|
||||||
|
{
|
||||||
|
var avg = fsql.Select<qt01>().AsQueryable().Max(a => a.id);
|
||||||
|
Assert.True(avg > 0);
|
||||||
|
}
|
||||||
|
[Fact]
|
||||||
|
public void Min()
|
||||||
|
{
|
||||||
|
var avg = fsql.Select<qt01>().AsQueryable().Min(a => a.id);
|
||||||
|
Assert.True(avg > 0);
|
||||||
|
}
|
||||||
|
[Fact]
|
||||||
|
public void Sum()
|
||||||
|
{
|
||||||
|
var avg = fsql.Select<qt01>().AsQueryable().Sum(a => a.id);
|
||||||
|
Assert.True(avg > 0);
|
||||||
|
}
|
||||||
|
[Fact]
|
||||||
|
public void Average()
|
||||||
|
{
|
||||||
|
var avg = fsql.Select<qt01>().AsQueryable().Average(a => a.id);
|
||||||
|
Assert.True(avg > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Contains()
|
||||||
|
{
|
||||||
|
Assert.True(fsql.Select<qt01>().AsQueryable().Contains(new qt01 { id = 1 }));
|
||||||
|
Assert.False(fsql.Select<qt01>().AsQueryable().Contains(new qt01 { id = 0 }));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Distinct()
|
||||||
|
{
|
||||||
|
fsql.Select<qt01>().AsQueryable().Distinct().Select(a => a.name).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ElementAt()
|
||||||
|
{
|
||||||
|
Assert.Equal(fsql.Select<qt01>().Skip(1).First().id, fsql.Select<qt01>().AsQueryable().ElementAt(1).id);
|
||||||
|
Assert.Equal(fsql.Select<qt01>().Skip(2).First().id, fsql.Select<qt01>().AsQueryable().ElementAt(2).id);
|
||||||
|
Assert.Equal(fsql.Select<qt01>().Skip(1).First().id, fsql.Select<qt01>().AsQueryable().ElementAtOrDefault(1).id);
|
||||||
|
Assert.Equal(fsql.Select<qt01>().Skip(2).First().id, fsql.Select<qt01>().AsQueryable().ElementAtOrDefault(2).id);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void First()
|
||||||
|
{
|
||||||
|
Assert.Equal(fsql.Select<qt01>().First().id, fsql.Select<qt01>().AsQueryable().First().id);
|
||||||
|
Assert.Equal(fsql.Select<qt01>().First().id, fsql.Select<qt01>().AsQueryable().FirstOrDefault().id);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Single()
|
||||||
|
{
|
||||||
|
Assert.Equal(fsql.Select<qt01>().First().id, fsql.Select<qt01>().AsQueryable().Single().id);
|
||||||
|
Assert.Equal(fsql.Select<qt01>().First().id, fsql.Select<qt01>().AsQueryable().SingleOrDefault().id);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void OrderBy()
|
||||||
|
{
|
||||||
|
Assert.Equal(fsql.Select<qt01>().OrderBy(a => a.id).First().id, fsql.Select<qt01>().AsQueryable().OrderBy(a => a.id).Single().id);
|
||||||
|
Assert.Equal(fsql.Select<qt01>().OrderBy(a => a.id).First().id, fsql.Select<qt01>().AsQueryable().OrderBy(a => a.id).SingleOrDefault().id);
|
||||||
|
}
|
||||||
|
[Fact]
|
||||||
|
public void OrderByDescending()
|
||||||
|
{
|
||||||
|
Assert.Equal(fsql.Select<qt01>().OrderByDescending(a => a.id).First().id, fsql.Select<qt01>().AsQueryable().OrderByDescending(a => a.id).Single().id);
|
||||||
|
Assert.Equal(fsql.Select<qt01>().OrderByDescending(a => a.id).First().id, fsql.Select<qt01>().AsQueryable().OrderByDescending(a => a.id).SingleOrDefault().id);
|
||||||
|
}
|
||||||
|
[Fact]
|
||||||
|
public void ThenBy()
|
||||||
|
{
|
||||||
|
Assert.Equal(fsql.Select<qt01>().OrderBy(a => a.id).OrderBy(a => a.id).First().id, fsql.Select<qt01>().AsQueryable().OrderBy(a => a.id).OrderBy(a => a.id).Single().id);
|
||||||
|
Assert.Equal(fsql.Select<qt01>().OrderBy(a => a.id).OrderBy(a => a.id).First().id, fsql.Select<qt01>().AsQueryable().OrderBy(a => a.id).OrderBy(a => a.id).SingleOrDefault().id);
|
||||||
|
|
||||||
|
Assert.Equal(fsql.Select<qt01>().OrderBy(a => a.id).OrderBy(a => a.id).First().id, fsql.Select<qt01>().AsQueryable().OrderBy(a => a.id).ThenBy(a => a.id).Single().id);
|
||||||
|
Assert.Equal(fsql.Select<qt01>().OrderBy(a => a.id).OrderBy(a => a.id).First().id, fsql.Select<qt01>().AsQueryable().OrderBy(a => a.id).ThenBy(a => a.id).SingleOrDefault().id);
|
||||||
|
}
|
||||||
|
[Fact]
|
||||||
|
public void ThenByDescending()
|
||||||
|
{
|
||||||
|
Assert.Equal(fsql.Select<qt01>().OrderBy(a => a.id).OrderByDescending(a => a.id).First().id, fsql.Select<qt01>().AsQueryable().OrderBy(a => a.id).OrderByDescending(a => a.id).Single().id);
|
||||||
|
Assert.Equal(fsql.Select<qt01>().OrderBy(a => a.id).OrderByDescending(a => a.id).First().id, fsql.Select<qt01>().AsQueryable().OrderBy(a => a.id).OrderByDescending(a => a.id).SingleOrDefault().id);
|
||||||
|
|
||||||
|
Assert.Equal(fsql.Select<qt01>().OrderBy(a => a.id).OrderByDescending(a => a.id).First().id, fsql.Select<qt01>().AsQueryable().OrderBy(a => a.id).ThenByDescending(a => a.id).Single().id);
|
||||||
|
Assert.Equal(fsql.Select<qt01>().OrderBy(a => a.id).OrderByDescending(a => a.id).First().id, fsql.Select<qt01>().AsQueryable().OrderBy(a => a.id).ThenByDescending(a => a.id).SingleOrDefault().id);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Select()
|
||||||
|
{
|
||||||
|
Assert.Equal(fsql.Select<qt01>().First(a => a.name), fsql.Select<qt01>().AsQueryable().Select(a => a.name).Single());
|
||||||
|
Assert.Equal(fsql.Select<qt01>().First(a => new { a.name }).name, fsql.Select<qt01>().AsQueryable().Select(a => new { a.name }).Single().name);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Where()
|
||||||
|
{
|
||||||
|
Assert.Equal(fsql.Select<qt01>().First(a => a.name), fsql.Select<qt01>().AsQueryable().Select(a => a.name).Single());
|
||||||
|
Assert.Equal(fsql.Select<qt01>().First(a => new { a.name }).name, fsql.Select<qt01>().AsQueryable().Select(a => new { a.name }).Single().name);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Skip()
|
||||||
|
{
|
||||||
|
Assert.Equal(fsql.Select<qt01>().Skip(2).First(a => a.name), fsql.Select<qt01>().AsQueryable().Skip(2).Select(a => a.name).Single());
|
||||||
|
Assert.Equal(fsql.Select<qt01>().Skip(2).First(a => new { a.name }).name, fsql.Select<qt01>().AsQueryable().Skip(2).Select(a => new { a.name }).Single().name);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Take()
|
||||||
|
{
|
||||||
|
Assert.Equal(fsql.Select<qt01>().Skip(2).First(a => a.name), fsql.Select<qt01>().AsQueryable().Skip(2).Take(1).Select(a => a.name).ToList().FirstOrDefault());
|
||||||
|
Assert.Equal(fsql.Select<qt01>().Skip(2).First(a => new { a.name }).name, fsql.Select<qt01>().AsQueryable().Skip(2).Take(1).Select(a => new { a.name }).ToList().FirstOrDefault().name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
15
FreeSql.sln
15
FreeSql.sln
@ -76,6 +76,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FreeSql.Extensions.EfCoreFl
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FreeSql.All", "FreeSql.All\FreeSql.All.csproj", "{933115AD-769C-4FBE-B000-2E8CF2292377}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FreeSql.All", "FreeSql.All\FreeSql.All.csproj", "{933115AD-769C-4FBE-B000-2E8CF2292377}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FreeSql.Extensions.Linq", "Extensions\FreeSql.Extensions.Linq\FreeSql.Extensions.Linq.csproj", "{57B3F5B0-D46A-4442-8EC6-9A9A784404B7}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@ -458,6 +460,18 @@ Global
|
|||||||
{933115AD-769C-4FBE-B000-2E8CF2292377}.Release|x64.Build.0 = Release|Any CPU
|
{933115AD-769C-4FBE-B000-2E8CF2292377}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{933115AD-769C-4FBE-B000-2E8CF2292377}.Release|x86.ActiveCfg = Release|Any CPU
|
{933115AD-769C-4FBE-B000-2E8CF2292377}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{933115AD-769C-4FBE-B000-2E8CF2292377}.Release|x86.Build.0 = Release|Any CPU
|
{933115AD-769C-4FBE-B000-2E8CF2292377}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{57B3F5B0-D46A-4442-8EC6-9A9A784404B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{57B3F5B0-D46A-4442-8EC6-9A9A784404B7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{57B3F5B0-D46A-4442-8EC6-9A9A784404B7}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{57B3F5B0-D46A-4442-8EC6-9A9A784404B7}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{57B3F5B0-D46A-4442-8EC6-9A9A784404B7}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{57B3F5B0-D46A-4442-8EC6-9A9A784404B7}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{57B3F5B0-D46A-4442-8EC6-9A9A784404B7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{57B3F5B0-D46A-4442-8EC6-9A9A784404B7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{57B3F5B0-D46A-4442-8EC6-9A9A784404B7}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{57B3F5B0-D46A-4442-8EC6-9A9A784404B7}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{57B3F5B0-D46A-4442-8EC6-9A9A784404B7}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{57B3F5B0-D46A-4442-8EC6-9A9A784404B7}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@ -484,6 +498,7 @@ Global
|
|||||||
{6A3A4470-7DF7-411B-AAD7-755D7A9DB5A4} = {4A92E8A6-9A6D-41A1-9CDA-DE10899648AA}
|
{6A3A4470-7DF7-411B-AAD7-755D7A9DB5A4} = {4A92E8A6-9A6D-41A1-9CDA-DE10899648AA}
|
||||||
{B397A761-F646-41CF-A160-AB6C05DAF2FB} = {2A381C57-2697-427B-9F10-55DA11FD02E4}
|
{B397A761-F646-41CF-A160-AB6C05DAF2FB} = {2A381C57-2697-427B-9F10-55DA11FD02E4}
|
||||||
{773D5B63-DE6E-46DB-AF16-6FB1C1352B3F} = {4A92E8A6-9A6D-41A1-9CDA-DE10899648AA}
|
{773D5B63-DE6E-46DB-AF16-6FB1C1352B3F} = {4A92E8A6-9A6D-41A1-9CDA-DE10899648AA}
|
||||||
|
{57B3F5B0-D46A-4442-8EC6-9A9A784404B7} = {4A92E8A6-9A6D-41A1-9CDA-DE10899648AA}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {089687FD-5D25-40AB-BA8A-A10D1E137F98}
|
SolutionGuid = {089687FD-5D25-40AB-BA8A-A10D1E137F98}
|
||||||
|
@ -993,31 +993,6 @@
|
|||||||
使用属性名作为字段别名
|
使用属性名作为字段别名
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:FreeSql.ILinqToSql`1.Select``1(System.Linq.Expressions.Expression{System.Func{`0,``0}})">
|
|
||||||
<summary>
|
|
||||||
【linq to sql】专用方法,不建议直接使用
|
|
||||||
</summary>
|
|
||||||
</member>
|
|
||||||
<member name="M:FreeSql.ILinqToSql`1.Join``3(FreeSql.ISelect{``0},System.Linq.Expressions.Expression{System.Func{`0,``1}},System.Linq.Expressions.Expression{System.Func{``0,``1}},System.Linq.Expressions.Expression{System.Func{`0,``0,``2}})">
|
|
||||||
<summary>
|
|
||||||
【linq to sql】专用方法,不建议直接使用
|
|
||||||
</summary>
|
|
||||||
</member>
|
|
||||||
<member name="M:FreeSql.ILinqToSql`1.GroupJoin``3(FreeSql.ISelect{``0},System.Linq.Expressions.Expression{System.Func{`0,``1}},System.Linq.Expressions.Expression{System.Func{``0,``1}},System.Linq.Expressions.Expression{System.Func{`0,FreeSql.ISelect{``0},``2}})">
|
|
||||||
<summary>
|
|
||||||
【linq to sql】专用方法,不建议直接使用
|
|
||||||
</summary>
|
|
||||||
</member>
|
|
||||||
<member name="M:FreeSql.ILinqToSql`1.DefaultIfEmpty">
|
|
||||||
<summary>
|
|
||||||
【linq to sql】专用方法,不建议直接使用
|
|
||||||
</summary>
|
|
||||||
</member>
|
|
||||||
<member name="M:FreeSql.ILinqToSql`1.SelectMany``2(System.Linq.Expressions.Expression{System.Func{`0,FreeSql.ISelect{``0}}},System.Linq.Expressions.Expression{System.Func{`0,``0,``1}})">
|
|
||||||
<summary>
|
|
||||||
【linq to sql】专用方法,不建议直接使用
|
|
||||||
</summary>
|
|
||||||
</member>
|
|
||||||
<member name="M:FreeSql.ISelect0`2.WithTransaction(System.Data.Common.DbTransaction)">
|
<member name="M:FreeSql.ISelect0`2.WithTransaction(System.Data.Common.DbTransaction)">
|
||||||
<summary>
|
<summary>
|
||||||
指定事务对象
|
指定事务对象
|
||||||
@ -1748,14 +1723,6 @@
|
|||||||
<param name="sql">SQL语句</param>
|
<param name="sql">SQL语句</param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:FreeSql.ISelect`1.AsQueryable">
|
|
||||||
<summary>
|
|
||||||
将 ISelect<T1> 转换为 IQueryable<T1><para></para>
|
|
||||||
此方法主要用于扩展,比如:abp IRepository GetAll() 接口方法需要返回 IQueryable 对象<para></para>
|
|
||||||
注意:IQueryable 方法污染较为严重,请尽量避免此转换
|
|
||||||
</summary>
|
|
||||||
<returns></returns>
|
|
||||||
</member>
|
|
||||||
<member name="M:FreeSql.ISelectFromExpression`1.Where(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
|
<member name="M:FreeSql.ISelectFromExpression`1.Where(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
|
||||||
<summary>
|
<summary>
|
||||||
查询条件,Where(a => a.Id > 10),支持导航对象查询,Where(a => a.Author.Email == "2881099@qq.com")
|
查询条件,Where(a => a.Id > 10),支持导航对象查询,Where(a => a.Author.Email == "2881099@qq.com")
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq.Expressions;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace FreeSql
|
|
||||||
{
|
|
||||||
public interface ILinqToSql<T1> where T1 : class
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 【linq to sql】专用方法,不建议直接使用
|
|
||||||
/// </summary>
|
|
||||||
ISelect<TReturn> Select<TReturn>(Expression<Func<T1, TReturn>> select) where TReturn : class;
|
|
||||||
/// <summary>
|
|
||||||
/// 【linq to sql】专用方法,不建议直接使用
|
|
||||||
/// </summary>
|
|
||||||
ISelect<TResult> Join<TInner, TKey, TResult>(ISelect<TInner> inner, Expression<Func<T1, TKey>> outerKeySelector, Expression<Func<TInner, TKey>> innerKeySelector, Expression<Func<T1, TInner, TResult>> resultSelector) where TInner : class where TResult : class;
|
|
||||||
/// <summary>
|
|
||||||
/// 【linq to sql】专用方法,不建议直接使用
|
|
||||||
/// </summary>
|
|
||||||
ISelect<TResult> GroupJoin<TInner, TKey, TResult>(ISelect<TInner> inner, Expression<Func<T1, TKey>> outerKeySelector, Expression<Func<TInner, TKey>> innerKeySelector, Expression<Func<T1, ISelect<TInner>, TResult>> resultSelector) where TInner : class where TResult : class;
|
|
||||||
/// <summary>
|
|
||||||
/// 【linq to sql】专用方法,不建议直接使用
|
|
||||||
/// </summary>
|
|
||||||
ISelect<T1> DefaultIfEmpty();
|
|
||||||
/// <summary>
|
|
||||||
/// 【linq to sql】专用方法,不建议直接使用
|
|
||||||
/// </summary>
|
|
||||||
ISelect<TResult> SelectMany<TCollection, TResult>(Expression<Func<T1, ISelect<TCollection>>> collectionSelector, Expression<Func<T1, TCollection, TResult>> resultSelector) where TCollection : class where TResult : class;
|
|
||||||
}
|
|
||||||
}
|
|
@ -7,7 +7,7 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace FreeSql
|
namespace FreeSql
|
||||||
{
|
{
|
||||||
public interface ISelect<T1> : ISelect0<ISelect<T1>, T1>, ILinqToSql<T1> where T1 : class
|
public interface ISelect<T1> : ISelect0<ISelect<T1>, T1> where T1 : class
|
||||||
{
|
{
|
||||||
|
|
||||||
#if net40
|
#if net40
|
||||||
@ -378,13 +378,5 @@ namespace FreeSql
|
|||||||
/// <param name="sql">SQL语句</param>
|
/// <param name="sql">SQL语句</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
ISelect<T1> WithSql(string sql);
|
ISelect<T1> WithSql(string sql);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 将 ISelect<T1> 转换为 IQueryable<T1><para></para>
|
|
||||||
/// 此方法主要用于扩展,比如:abp IRepository GetAll() 接口方法需要返回 IQueryable 对象<para></para>
|
|
||||||
/// 注意:IQueryable 方法污染较为严重,请尽量避免此转换
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
IQueryable<T1> AsQueryable();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,17 +1,18 @@
|
|||||||
using FreeSql.Internal.Model;
|
using FreeSql.DataAnnotations;
|
||||||
|
using FreeSql.Internal.CommonProvider;
|
||||||
|
using FreeSql.Internal.Model;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Data.Common;
|
using System.Data.Common;
|
||||||
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using FreeSql.DataAnnotations;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Globalization;
|
|
||||||
|
|
||||||
namespace FreeSql.Internal
|
namespace FreeSql.Internal
|
||||||
{
|
{
|
||||||
@ -19,8 +20,8 @@ namespace FreeSql.Internal
|
|||||||
{
|
{
|
||||||
|
|
||||||
public CommonUtils _common;
|
public CommonUtils _common;
|
||||||
public CommonProvider.AdoProvider _ado => _adoPriv ?? (_adoPriv = _common._orm.Ado as CommonProvider.AdoProvider);
|
public AdoProvider _ado => _adoPriv ?? (_adoPriv = _common._orm.Ado as AdoProvider);
|
||||||
CommonProvider.AdoProvider _adoPriv;
|
AdoProvider _adoPriv;
|
||||||
public CommonExpression(CommonUtils common)
|
public CommonExpression(CommonUtils common)
|
||||||
{
|
{
|
||||||
_common = common;
|
_common = common;
|
||||||
@ -692,14 +693,6 @@ namespace FreeSql.Internal
|
|||||||
}
|
}
|
||||||
if (callType.FullName.StartsWith("FreeSql.ISelectGroupingAggregate`"))
|
if (callType.FullName.StartsWith("FreeSql.ISelectGroupingAggregate`"))
|
||||||
{
|
{
|
||||||
//if (exp3.Type == typeof(string) && exp3.Arguments.Any() && exp3.Arguments[0].NodeType == ExpressionType.Constant) {
|
|
||||||
// switch (exp3.Method.Name) {
|
|
||||||
// case "Sum": return $"sum({(exp3.Arguments[0] as ConstantExpression)?.Value})";
|
|
||||||
// case "Avg": return $"avg({(exp3.Arguments[0] as ConstantExpression)?.Value})";
|
|
||||||
// case "Max": return $"max({(exp3.Arguments[0] as ConstantExpression)?.Value})";
|
|
||||||
// case "Min": return $"min({(exp3.Arguments[0] as ConstantExpression)?.Value})";
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
switch (exp3.Method.Name)
|
switch (exp3.Method.Name)
|
||||||
{
|
{
|
||||||
case "Count": return exp3.Arguments.Count == 0 ? "count(1)" : $"count({ExpressionLambdaToSql(exp3.Arguments[0], tsc)})";
|
case "Count": return exp3.Arguments.Count == 0 ? "count(1)" : $"count({ExpressionLambdaToSql(exp3.Arguments[0], tsc)})";
|
||||||
@ -819,11 +812,10 @@ namespace FreeSql.Internal
|
|||||||
if (fsql == null) fsql = Expression.Lambda(exp3tmp).Compile().DynamicInvoke();
|
if (fsql == null) fsql = Expression.Lambda(exp3tmp).Compile().DynamicInvoke();
|
||||||
fsqlType = fsql?.GetType();
|
fsqlType = fsql?.GetType();
|
||||||
if (fsqlType == null) break;
|
if (fsqlType == null) break;
|
||||||
if (exp3.Method.Name != "ToList")
|
var fsqlSelect0 = fsql as Select0Provider;
|
||||||
fsqlType.GetField("_limit", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(fsql, 1);
|
if (exp3.Method.Name != "ToList") fsqlSelect0._limit = 1;
|
||||||
if (tsc.dbParams != null)
|
if (tsc.dbParams != null) fsqlSelect0._params = tsc.dbParams;
|
||||||
fsqlType.GetField("_params", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(fsql, tsc.dbParams);
|
fsqltables = fsqlSelect0._tables;
|
||||||
fsqltables = fsqlType.GetField("_tables", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(fsql) as List<SelectTableInfo>;
|
|
||||||
//fsqltables[0].Alias = $"{tsc._tables[0].Alias}_{fsqltables[0].Alias}";
|
//fsqltables[0].Alias = $"{tsc._tables[0].Alias}_{fsqltables[0].Alias}";
|
||||||
if (fsqltables != tsc._tables)
|
if (fsqltables != tsc._tables)
|
||||||
fsqltables.AddRange(tsc._tables.Select(a => new SelectTableInfo
|
fsqltables.AddRange(tsc._tables.Select(a => new SelectTableInfo
|
||||||
@ -836,7 +828,7 @@ namespace FreeSql.Internal
|
|||||||
}));
|
}));
|
||||||
if (tsc.whereCascadeExpression?.Any() == true)
|
if (tsc.whereCascadeExpression?.Any() == true)
|
||||||
{
|
{
|
||||||
var fsqlCascade = fsqlType.GetField("_whereCascadeExpression", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(fsql) as List<LambdaExpression>;
|
var fsqlCascade = fsqlSelect0._whereCascadeExpression;
|
||||||
if (fsqlCascade != tsc.whereCascadeExpression)
|
if (fsqlCascade != tsc.whereCascadeExpression)
|
||||||
fsqlCascade.AddRange(tsc.whereCascadeExpression);
|
fsqlCascade.AddRange(tsc.whereCascadeExpression);
|
||||||
}
|
}
|
||||||
@ -1022,12 +1014,6 @@ namespace FreeSql.Internal
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//var eleType = callType.GetElementType() ?? callType.GenericTypeArguments.FirstOrDefault();
|
|
||||||
//if (eleType != null && typeof(IEnumerable<>).MakeGenericType(eleType).IsAssignableFrom(callType)) { //集合导航属性子查询
|
|
||||||
// if (exp3.Method.Name == "Any") { //exists
|
|
||||||
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
other3Exp = ExpressionLambdaToSqlOther(exp3, tsc);
|
other3Exp = ExpressionLambdaToSqlOther(exp3, tsc);
|
||||||
if (string.IsNullOrEmpty(other3Exp) == false) return other3Exp;
|
if (string.IsNullOrEmpty(other3Exp) == false) return other3Exp;
|
||||||
if (exp3.IsParameter() == false) return formatSql(Expression.Lambda(exp3).Compile().DynamicInvoke(), tsc.mapType, tsc.mapColumnTmp, tsc.dbParams);
|
if (exp3.IsParameter() == false) return formatSql(Expression.Lambda(exp3).Compile().DynamicInvoke(), tsc.mapType, tsc.mapColumnTmp, tsc.dbParams);
|
||||||
@ -1107,7 +1093,10 @@ namespace FreeSql.Internal
|
|||||||
break;
|
break;
|
||||||
case ExpressionType.MemberAccess:
|
case ExpressionType.MemberAccess:
|
||||||
var expStackFirstMem = expStack.First() as MemberExpression;
|
var expStackFirstMem = expStack.First() as MemberExpression;
|
||||||
if (expStackFirstMem.Expression?.NodeType == ExpressionType.Constant) firstValue = (expStackFirstMem.Expression as ConstantExpression)?.Value;
|
if (expStackFirstMem.Expression?.NodeType == ExpressionType.Constant)
|
||||||
|
firstValue = (expStackFirstMem.Expression as ConstantExpression)?.Value;
|
||||||
|
else
|
||||||
|
return formatSql(Expression.Lambda(exp).Compile().DynamicInvoke(), tsc.mapType, tsc.mapColumnTmp, tsc.dbParams);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
while (expStack.Any())
|
while (expStack.Any())
|
||||||
|
@ -16,7 +16,6 @@ namespace FreeSql.Internal.CommonProvider
|
|||||||
|
|
||||||
public abstract partial class CodeFirstProvider : ICodeFirst
|
public abstract partial class CodeFirstProvider : ICodeFirst
|
||||||
{
|
{
|
||||||
|
|
||||||
public IFreeSql _orm;
|
public IFreeSql _orm;
|
||||||
public CommonUtils _commonUtils;
|
public CommonUtils _commonUtils;
|
||||||
public CommonExpression _commonExpression;
|
public CommonExpression _commonExpression;
|
||||||
@ -78,7 +77,7 @@ namespace FreeSql.Internal.CommonProvider
|
|||||||
_dicSynced.TryAdd(entityType, trydic = new ConcurrentDictionary<string, bool>());
|
_dicSynced.TryAdd(entityType, trydic = new ConcurrentDictionary<string, bool>());
|
||||||
return trydic;
|
return trydic;
|
||||||
}
|
}
|
||||||
internal void _dicSycedTryAdd(Type entityType, string tableName = null) =>
|
public void _dicSycedTryAdd(Type entityType, string tableName = null) =>
|
||||||
_dicSycedGetOrAdd(entityType).TryAdd(GetTableNameLowerOrUpper(tableName), true);
|
_dicSycedGetOrAdd(entityType).TryAdd(GetTableNameLowerOrUpper(tableName), true);
|
||||||
|
|
||||||
public void SyncStructure<TEntity>() =>
|
public void SyncStructure<TEntity>() =>
|
||||||
|
@ -1,107 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Linq.Expressions;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace FreeSql.Internal.CommonProvider
|
|
||||||
{
|
|
||||||
class QueryableProvider<T> : IQueryable<T>
|
|
||||||
{
|
|
||||||
private Expression _expression;
|
|
||||||
private IQueryProvider _provider;
|
|
||||||
private object _select;
|
|
||||||
private CommonExpression _commonExpression;
|
|
||||||
|
|
||||||
public QueryableProvider(object select)
|
|
||||||
{
|
|
||||||
_select = select;
|
|
||||||
_commonExpression = _select.GetType().GetField("_commonExpression", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(_select) as CommonExpression;
|
|
||||||
_expression = Expression.Constant(this);
|
|
||||||
_provider = new QueryProvider<T>(_select, _commonExpression);
|
|
||||||
}
|
|
||||||
public QueryableProvider(Expression expression, IQueryProvider provider, object select, CommonExpression commonExpression)
|
|
||||||
{
|
|
||||||
_select = select;
|
|
||||||
_commonExpression = commonExpression;
|
|
||||||
_expression = expression;
|
|
||||||
_provider = provider;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerator<T> GetEnumerator()
|
|
||||||
{
|
|
||||||
var result = _provider.Execute<List<T>>(_expression);
|
|
||||||
if (result == null)
|
|
||||||
yield break;
|
|
||||||
foreach (var item in result)
|
|
||||||
{
|
|
||||||
yield return item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();
|
|
||||||
|
|
||||||
public Type ElementType => typeof(QueryableProvider<T>);
|
|
||||||
public Expression Expression => _expression;
|
|
||||||
public IQueryProvider Provider => _provider;
|
|
||||||
}
|
|
||||||
|
|
||||||
class QueryProvider<T> : IQueryProvider
|
|
||||||
{
|
|
||||||
private object _select;
|
|
||||||
private CommonExpression _commonExpression;
|
|
||||||
|
|
||||||
public QueryProvider(object select, CommonExpression commonExpression)
|
|
||||||
{
|
|
||||||
_select = select;
|
|
||||||
_commonExpression = commonExpression;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
|
|
||||||
{
|
|
||||||
IQueryable<TElement> query = new QueryableProvider<TElement>(expression, this, _select, _commonExpression);
|
|
||||||
return query;
|
|
||||||
}
|
|
||||||
public IQueryable CreateQuery(Expression expression) => throw new NotImplementedException();
|
|
||||||
|
|
||||||
|
|
||||||
public TResult Execute<TResult>(Expression expression)
|
|
||||||
{
|
|
||||||
var methodExp = expression as MethodCallExpression;
|
|
||||||
while (methodExp != null)
|
|
||||||
{
|
|
||||||
switch (methodExp.Method.Name)
|
|
||||||
{
|
|
||||||
case "First":
|
|
||||||
case "FirstOrDefault":
|
|
||||||
_select.GetType().GetMethod("Limit", new[] { typeof(int) }).Invoke(_select, new object[] { 1 });
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
var selectMethod = _select.GetType().GetMethod(methodExp.Method.Name, methodExp.Arguments.Where((a, b) => b > 0).Select(a => a.Type).ToArray());
|
|
||||||
if (selectMethod == null) throw new Exception($"无法找到 ISelect.{methodExp.Method.Name}({string.Join(", ", methodExp.Arguments.Select(a => a.Type.FullName))}) 方法");
|
|
||||||
|
|
||||||
var selectArgs = methodExp.Arguments.Where((a, b) => b > 0).Select(a =>
|
|
||||||
{
|
|
||||||
switch (a.NodeType)
|
|
||||||
{
|
|
||||||
case ExpressionType.Lambda: return (object)a;
|
|
||||||
default: return Expression.Lambda(a).Compile().DynamicInvoke();
|
|
||||||
}
|
|
||||||
}).ToArray();
|
|
||||||
selectMethod.Invoke(_select, selectArgs);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
methodExp = methodExp.Arguments.FirstOrDefault() as MethodCallExpression;
|
|
||||||
}
|
|
||||||
var resultType = typeof(TResult);
|
|
||||||
var resultTypeIsList = typeof(IList).IsAssignableFrom(resultType);
|
|
||||||
if (resultTypeIsList) resultType = resultType.GetGenericArguments()[0];
|
|
||||||
var ret = _select.GetType().GetMethod(resultTypeIsList ? "ToList" : "First", new Type[0])
|
|
||||||
.MakeGenericMethod(resultType)
|
|
||||||
.Invoke(_select, new object[0]);
|
|
||||||
return (TResult)ret;
|
|
||||||
}
|
|
||||||
public object Execute(Expression expression) => throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
|
@ -16,33 +16,32 @@ using System.Threading.Tasks;
|
|||||||
namespace FreeSql.Internal.CommonProvider
|
namespace FreeSql.Internal.CommonProvider
|
||||||
{
|
{
|
||||||
|
|
||||||
public abstract partial class Select0Provider<TSelect, T1> : ISelect0<TSelect, T1> where TSelect : class where T1 : class
|
public abstract partial class Select0Provider
|
||||||
{
|
{
|
||||||
|
public int _limit, _skip;
|
||||||
protected int _limit, _skip;
|
public string _select = "SELECT ", _orderby, _groupby, _having;
|
||||||
protected string _select = "SELECT ", _orderby, _groupby, _having;
|
public StringBuilder _where = new StringBuilder();
|
||||||
protected StringBuilder _where = new StringBuilder();
|
public List<DbParameter> _params = new List<DbParameter>();
|
||||||
protected List<DbParameter> _params = new List<DbParameter>();
|
public List<SelectTableInfo> _tables = new List<SelectTableInfo>();
|
||||||
internal protected List<SelectTableInfo> _tables = new List<SelectTableInfo>();
|
public List<Func<Type, string, string>> _tableRules = new List<Func<Type, string, string>>();
|
||||||
protected List<Func<Type, string, string>> _tableRules = new List<Func<Type, string, string>>();
|
public Func<Type, string, string> _aliasRule;
|
||||||
protected Func<Type, string, string> _aliasRule;
|
public string _tosqlAppendContent;
|
||||||
protected string _tosqlAppendContent;
|
public StringBuilder _join = new StringBuilder();
|
||||||
protected StringBuilder _join = new StringBuilder();
|
public IFreeSql _orm;
|
||||||
internal protected IFreeSql _orm;
|
public CommonUtils _commonUtils;
|
||||||
protected CommonUtils _commonUtils;
|
public CommonExpression _commonExpression;
|
||||||
protected CommonExpression _commonExpression;
|
public DbTransaction _transaction;
|
||||||
protected DbTransaction _transaction;
|
public DbConnection _connection;
|
||||||
protected DbConnection _connection;
|
public Action<object> _trackToList;
|
||||||
internal protected Action<object> _trackToList;
|
public List<Action<object>> _includeToList = new List<Action<object>>();
|
||||||
internal protected List<Action<object>> _includeToList = new List<Action<object>>();
|
|
||||||
#if net40
|
#if net40
|
||||||
#else
|
#else
|
||||||
protected List<Func<object, Task>> _includeToListAsync = new List<Func<object, Task>>();
|
public List<Func<object, Task>> _includeToListAsync = new List<Func<object, Task>>();
|
||||||
#endif
|
#endif
|
||||||
protected bool _distinct;
|
public bool _distinct;
|
||||||
protected Expression _selectExpression;
|
public Expression _selectExpression;
|
||||||
protected List<LambdaExpression> _whereCascadeExpression = new List<LambdaExpression>();
|
public List<LambdaExpression> _whereCascadeExpression = new List<LambdaExpression>();
|
||||||
protected List<GlobalFilter.Item> _whereGlobalFilter;
|
public List<GlobalFilter.Item> _whereGlobalFilter;
|
||||||
|
|
||||||
int _disposeCounter;
|
int _disposeCounter;
|
||||||
~Select0Provider()
|
~Select0Provider()
|
||||||
@ -64,24 +63,25 @@ namespace FreeSql.Internal.CommonProvider
|
|||||||
_whereGlobalFilter = _orm.GlobalFilter.GetFilters();
|
_whereGlobalFilter = _orm.GlobalFilter.GetFilters();
|
||||||
_whereCascadeExpression.AddRange(_whereGlobalFilter.Select(a => a.Where));
|
_whereCascadeExpression.AddRange(_whereGlobalFilter.Select(a => a.Where));
|
||||||
}
|
}
|
||||||
public static void CopyData(Select0Provider<TSelect, T1> from, object to, ReadOnlyCollection<ParameterExpression> lambParms)
|
|
||||||
|
public static void CopyData(Select0Provider from, Select0Provider to, ReadOnlyCollection<ParameterExpression> lambParms)
|
||||||
{
|
{
|
||||||
var toType = to?.GetType();
|
if (to == null) return;
|
||||||
if (toType == null) return;
|
to._limit = from._limit;
|
||||||
toType.GetField("_limit", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._limit);
|
to._skip = from._skip;
|
||||||
toType.GetField("_skip", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._skip);
|
to._select = from._select;
|
||||||
toType.GetField("_select", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._select);
|
to._orderby = from._orderby;
|
||||||
toType.GetField("_orderby", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._orderby);
|
to._groupby = from._groupby;
|
||||||
toType.GetField("_groupby", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._groupby);
|
to._having = from._having;
|
||||||
toType.GetField("_having", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._having);
|
to._where = new StringBuilder().Append(from._where.ToString());
|
||||||
toType.GetField("_where", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, new StringBuilder().Append(from._where.ToString()));
|
to._params = new List<DbParameter>(from._params.ToArray());
|
||||||
toType.GetField("_params", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, new List<DbParameter>(from._params.ToArray()));
|
|
||||||
if (lambParms == null)
|
if (lambParms == null)
|
||||||
toType.GetField("_tables", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, new List<SelectTableInfo>(from._tables.ToArray()));
|
to._tables = new List<SelectTableInfo>(from._tables.ToArray());
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var findedIndexs = new List<int>();
|
var findedIndexs = new List<int>();
|
||||||
var _multiTables = toType.GetField("_tables", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(to) as List<SelectTableInfo>;
|
var _multiTables = to._tables;
|
||||||
_multiTables[0] = from._tables[0];
|
_multiTables[0] = from._tables[0];
|
||||||
for (var a = 1; a < lambParms.Count; a++)
|
for (var a = 1; a < lambParms.Count; a++)
|
||||||
{
|
{
|
||||||
@ -103,26 +103,29 @@ namespace FreeSql.Internal.CommonProvider
|
|||||||
_multiTables.Add(from._tables[a]);
|
_multiTables.Add(from._tables[a]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
toType.GetField("_tableRules", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, new List<Func<Type, string, string>>(from._tableRules.ToArray()));
|
to._tableRules = new List<Func<Type, string, string>>(from._tableRules.ToArray());
|
||||||
toType.GetField("_aliasRule", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._aliasRule);
|
to._aliasRule = from._aliasRule;
|
||||||
toType.GetField("_join", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, new StringBuilder().Append(from._join.ToString()));
|
to._join = new StringBuilder().Append(from._join.ToString());
|
||||||
//toType.GetField("_orm", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._orm);
|
//to._orm = from._orm;
|
||||||
//toType.GetField("_commonUtils", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._commonUtils);
|
//to._commonUtils = from._commonUtils;
|
||||||
//toType.GetField("_commonExpression", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._commonExpression);
|
//to._commonExpression = from._commonExpression;
|
||||||
toType.GetField("_transaction", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._transaction);
|
to._transaction = from._transaction;
|
||||||
toType.GetField("_connection", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._connection);
|
to._connection = from._connection;
|
||||||
toType.GetField("_trackToList", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._trackToList);
|
to._trackToList = from._trackToList;
|
||||||
toType.GetField("_includeToList", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, new List<Action<object>>(from._includeToList.ToArray()));
|
to._includeToList = new List<Action<object>>(from._includeToList.ToArray());
|
||||||
#if net40
|
#if net40
|
||||||
#else
|
#else
|
||||||
toType.GetField("_includeToListAsync", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, new List<Func<object, Task>>(from._includeToListAsync.ToArray()));
|
to._includeToListAsync = new List<Func<object, Task>>(from._includeToListAsync.ToArray());
|
||||||
#endif
|
#endif
|
||||||
toType.GetField("_distinct", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._distinct);
|
to._distinct = from._distinct;
|
||||||
toType.GetField("_selectExpression", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._selectExpression);
|
to._selectExpression = from._selectExpression;
|
||||||
toType.GetField("_whereCascadeExpression", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, new List<LambdaExpression>(from._whereCascadeExpression.ToArray()));
|
to._whereCascadeExpression = new List<LambdaExpression>(from._whereCascadeExpression.ToArray());
|
||||||
toType.GetField("_whereGlobalFilter", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, new List<GlobalFilter.Item>(from._whereGlobalFilter.ToArray()));
|
to._whereGlobalFilter = new List<GlobalFilter.Item>(from._whereGlobalFilter.ToArray());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract partial class Select0Provider<TSelect, T1> : Select0Provider, ISelect0<TSelect, T1> where TSelect : class where T1 : class
|
||||||
|
{
|
||||||
public Select0Provider(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere)
|
public Select0Provider(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere)
|
||||||
{
|
{
|
||||||
_orm = orm;
|
_orm = orm;
|
||||||
@ -1082,7 +1085,7 @@ namespace FreeSql.Internal.CommonProvider
|
|||||||
protected TMember InternalMin<TMember>(Expression exp) => this.ToList<TMember>($"min({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true, null)}){_commonUtils.FieldAsAlias("as1")}").Min();
|
protected TMember InternalMin<TMember>(Expression exp) => this.ToList<TMember>($"min({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true, null)}){_commonUtils.FieldAsAlias("as1")}").Min();
|
||||||
protected decimal InternalSum(Expression exp) => this.ToList<decimal>($"sum({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true, null)}){_commonUtils.FieldAsAlias("as1")}").Sum();
|
protected decimal InternalSum(Expression exp) => this.ToList<decimal>($"sum({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true, null)}){_commonUtils.FieldAsAlias("as1")}").Sum();
|
||||||
|
|
||||||
protected ISelectGrouping<TKey, TValue> InternalGroupBy<TKey, TValue>(Expression columns)
|
public ISelectGrouping<TKey, TValue> InternalGroupBy<TKey, TValue>(Expression columns)
|
||||||
{
|
{
|
||||||
var map = new ReadAnonymousTypeInfo();
|
var map = new ReadAnonymousTypeInfo();
|
||||||
var field = new StringBuilder();
|
var field = new StringBuilder();
|
||||||
@ -1093,7 +1096,7 @@ namespace FreeSql.Internal.CommonProvider
|
|||||||
this.GroupBy(sql.Length > 0 ? sql.Substring(2) : null);
|
this.GroupBy(sql.Length > 0 ? sql.Substring(2) : null);
|
||||||
return new SelectGroupingProvider<TKey, TValue>(_orm, this, map, sql, _commonExpression, _tables);
|
return new SelectGroupingProvider<TKey, TValue>(_orm, this, map, sql, _commonExpression, _tables);
|
||||||
}
|
}
|
||||||
protected TSelect InternalJoin(Expression exp, SelectTableInfoType joinType)
|
public TSelect InternalJoin(Expression exp, SelectTableInfoType joinType)
|
||||||
{
|
{
|
||||||
_commonExpression.ExpressionJoinLambda(_tables, joinType, exp, null, _whereCascadeExpression);
|
_commonExpression.ExpressionJoinLambda(_tables, joinType, exp, null, _whereCascadeExpression);
|
||||||
return this as TSelect;
|
return this as TSelect;
|
||||||
@ -1109,7 +1112,7 @@ namespace FreeSql.Internal.CommonProvider
|
|||||||
protected TSelect InternalOrderBy(Expression column) => this.OrderBy(_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, column, true, null));
|
protected TSelect InternalOrderBy(Expression column) => this.OrderBy(_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, column, true, null));
|
||||||
protected TSelect InternalOrderByDescending(Expression column) => this.OrderBy($"{_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, column, true, null)} DESC");
|
protected TSelect InternalOrderByDescending(Expression column) => this.OrderBy($"{_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, column, true, null)} DESC");
|
||||||
|
|
||||||
protected List<TReturn> InternalToList<TReturn>(Expression select) => this.ToListMapReader<TReturn>(this.GetExpressionField(select));
|
public List<TReturn> InternalToList<TReturn>(Expression select) => this.ToListMapReader<TReturn>(this.GetExpressionField(select));
|
||||||
protected string InternalToSql<TReturn>(Expression select, FieldAliasOptions fieldAlias = FieldAliasOptions.AsIndex)
|
protected string InternalToSql<TReturn>(Expression select, FieldAliasOptions fieldAlias = FieldAliasOptions.AsIndex)
|
||||||
{
|
{
|
||||||
var af = this.GetExpressionField(select, fieldAlias);
|
var af = this.GetExpressionField(select, fieldAlias);
|
||||||
@ -1151,7 +1154,7 @@ namespace FreeSql.Internal.CommonProvider
|
|||||||
return this.ToListMapReader<TReturn>(new ReadAnonymousTypeAfInfo(map, field.Length > 0 ? field.Remove(0, 2).ToString() : null)).FirstOrDefault();
|
return this.ToListMapReader<TReturn>(new ReadAnonymousTypeAfInfo(map, field.Length > 0 ? field.Remove(0, 2).ToString() : null)).FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected TSelect InternalWhere(Expression exp) => exp == null ? this as TSelect : this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp, null, _whereCascadeExpression, _params));
|
public TSelect InternalWhere(Expression exp) => exp == null ? this as TSelect : this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp, null, _whereCascadeExpression, _params));
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#if net40
|
#if net40
|
||||||
|
@ -111,15 +111,15 @@ namespace FreeSql.Internal.CommonProvider
|
|||||||
return this.InternalAvg(column?.Body);
|
return this.InternalAvg(column?.Body);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract ISelect<T1, T2> From<T2>(Expression<Func<ISelectFromExpression<T1>, T2, ISelectFromExpression<T1>>> exp) where T2 : class;// { this.InternalFrom(exp); var ret = new Select3Provider<T1, T2, T3>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, exp?.Parameters); return ret; }
|
public abstract ISelect<T1, T2> From<T2>(Expression<Func<ISelectFromExpression<T1>, T2, ISelectFromExpression<T1>>> exp) where T2 : class;
|
||||||
public abstract ISelect<T1, T2, T3> From<T2, T3>(Expression<Func<ISelectFromExpression<T1>, T2, T3, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class;// { this.InternalFrom(exp); var ret = new Select3Provider<T1, T2, T3>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, exp?.Parameters); return ret; }
|
public abstract ISelect<T1, T2, T3> From<T2, T3>(Expression<Func<ISelectFromExpression<T1>, T2, T3, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class;
|
||||||
public abstract ISelect<T1, T2, T3, T4> From<T2, T3, T4>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class where T4 : class;// { this.InternalFrom(exp); var ret = new Select4Provider<T1, T2, T3, T4>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, exp?.Parameters); return ret; }
|
public abstract ISelect<T1, T2, T3, T4> From<T2, T3, T4>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class where T4 : class;
|
||||||
public abstract ISelect<T1, T2, T3, T4, T5> From<T2, T3, T4, T5>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class where T4 : class where T5 : class;// { this.InternalFrom(exp); var ret = new Select5Provider<T1, T2, T3, T4, T5>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, exp?.Parameters); return ret; }
|
public abstract ISelect<T1, T2, T3, T4, T5> From<T2, T3, T4, T5>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class where T4 : class where T5 : class;
|
||||||
public abstract ISelect<T1, T2, T3, T4, T5, T6> From<T2, T3, T4, T5, T6>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class;// { this.InternalFrom(exp); var ret = new Select6Provider<T1, T2, T3, T4, T5, T6>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, exp?.Parameters); return ret; }
|
public abstract ISelect<T1, T2, T3, T4, T5, T6> From<T2, T3, T4, T5, T6>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class;
|
||||||
public abstract ISelect<T1, T2, T3, T4, T5, T6, T7> From<T2, T3, T4, T5, T6, T7>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class;// { this.InternalFrom(exp); var ret = new Select7Provider<T1, T2, T3, T4, T5, T6, T7>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, exp?.Parameters); return ret; }
|
public abstract ISelect<T1, T2, T3, T4, T5, T6, T7> From<T2, T3, T4, T5, T6, T7>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class;
|
||||||
public abstract ISelect<T1, T2, T3, T4, T5, T6, T7, T8> From<T2, T3, T4, T5, T6, T7, T8>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class;// { this.InternalFrom(exp); var ret = new Select8Provider<T1, T2, T3, T4, T5, T6, T7, T8>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, exp?.Parameters); return ret; }
|
public abstract ISelect<T1, T2, T3, T4, T5, T6, T7, T8> From<T2, T3, T4, T5, T6, T7, T8>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class;
|
||||||
public abstract ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> From<T2, T3, T4, T5, T6, T7, T8, T9>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, T9, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class;// { this.InternalFrom(exp); var ret = new Select9Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, exp?.Parameters); return ret; }
|
public abstract ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> From<T2, T3, T4, T5, T6, T7, T8, T9>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, T9, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class;
|
||||||
public abstract ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> From<T2, T3, T4, T5, T6, T7, T8, T9, T10>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, T9, T10, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class where T10 : class;// { this.InternalFrom(exp); var ret = new Select10Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, exp?.Parameters); return ret; }
|
public abstract ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> From<T2, T3, T4, T5, T6, T7, T8, T9, T10>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, T9, T10, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class where T10 : class;
|
||||||
|
|
||||||
public ISelectGrouping<TKey, T1> GroupBy<TKey>(Expression<Func<T1, TKey>> columns)
|
public ISelectGrouping<TKey, T1> GroupBy<TKey>(Expression<Func<T1, TKey>> columns)
|
||||||
{
|
{
|
||||||
@ -132,41 +132,48 @@ namespace FreeSql.Internal.CommonProvider
|
|||||||
{
|
{
|
||||||
if (column == null) return default(TMember);
|
if (column == null) return default(TMember);
|
||||||
_tables[0].Parameter = column.Parameters[0];
|
_tables[0].Parameter = column.Parameters[0];
|
||||||
return this.InternalMax<TMember>(column?.Body);
|
return this.InternalMax<TMember>(column.Body);
|
||||||
}
|
}
|
||||||
public TMember Min<TMember>(Expression<Func<T1, TMember>> column)
|
public TMember Min<TMember>(Expression<Func<T1, TMember>> column)
|
||||||
{
|
{
|
||||||
if (column == null) return default(TMember);
|
if (column == null) return default(TMember);
|
||||||
_tables[0].Parameter = column.Parameters[0];
|
_tables[0].Parameter = column.Parameters[0];
|
||||||
return this.InternalMin<TMember>(column?.Body);
|
return this.InternalMin<TMember>(column.Body);
|
||||||
|
}
|
||||||
|
public void OrderByReflection(LambdaExpression column, bool isDescending)
|
||||||
|
{
|
||||||
|
if (column == null) return;
|
||||||
|
_tables[0].Parameter = column.Parameters[0];
|
||||||
|
if (isDescending) this.InternalOrderByDescending(column.Body);
|
||||||
|
else this.InternalOrderBy(column.Body);
|
||||||
}
|
}
|
||||||
public ISelect<T1> OrderBy<TMember>(Expression<Func<T1, TMember>> column) => this.OrderBy(true, column);
|
public ISelect<T1> OrderBy<TMember>(Expression<Func<T1, TMember>> column) => this.OrderBy(true, column);
|
||||||
public ISelect<T1> OrderBy<TMember>(bool condition, Expression<Func<T1, TMember>> column)
|
public ISelect<T1> OrderBy<TMember>(bool condition, Expression<Func<T1, TMember>> column)
|
||||||
{
|
{
|
||||||
if (condition == false || column == null) return this;
|
if (condition == false || column == null) return this;
|
||||||
_tables[0].Parameter = column.Parameters[0];
|
_tables[0].Parameter = column.Parameters[0];
|
||||||
return this.InternalOrderBy(column?.Body);
|
return this.InternalOrderBy(column.Body);
|
||||||
}
|
}
|
||||||
public ISelect<T1> OrderByDescending<TMember>(Expression<Func<T1, TMember>> column) => this.OrderByDescending(true, column);
|
public ISelect<T1> OrderByDescending<TMember>(Expression<Func<T1, TMember>> column) => this.OrderByDescending(true, column);
|
||||||
public ISelect<T1> OrderByDescending<TMember>(bool condition, Expression<Func<T1, TMember>> column)
|
public ISelect<T1> OrderByDescending<TMember>(bool condition, Expression<Func<T1, TMember>> column)
|
||||||
{
|
{
|
||||||
if (condition == false || column == null) return this;
|
if (condition == false || column == null) return this;
|
||||||
_tables[0].Parameter = column.Parameters[0];
|
_tables[0].Parameter = column.Parameters[0];
|
||||||
return this.InternalOrderByDescending(column?.Body);
|
return this.InternalOrderByDescending(column.Body);
|
||||||
}
|
}
|
||||||
|
|
||||||
public decimal Sum<TMember>(Expression<Func<T1, TMember>> column)
|
public decimal Sum<TMember>(Expression<Func<T1, TMember>> column)
|
||||||
{
|
{
|
||||||
if (column == null) return default(decimal);
|
if (column == null) return default(decimal);
|
||||||
_tables[0].Parameter = column.Parameters[0];
|
_tables[0].Parameter = column.Parameters[0];
|
||||||
return this.InternalSum(column?.Body);
|
return this.InternalSum(column.Body);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<TReturn> ToList<TReturn>(Expression<Func<T1, TReturn>> select)
|
public List<TReturn> ToList<TReturn>(Expression<Func<T1, TReturn>> select)
|
||||||
{
|
{
|
||||||
if (select == null) return this.InternalToList<TReturn>(select?.Body);
|
if (select == null) return this.InternalToList<TReturn>(select?.Body);
|
||||||
_tables[0].Parameter = select.Parameters[0];
|
_tables[0].Parameter = select.Parameters[0];
|
||||||
return this.InternalToList<TReturn>(select?.Body);
|
return this.InternalToList<TReturn>(select.Body);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<TDto> ToList<TDto>() => ToList(GetToListDtoSelector<TDto>());
|
public List<TDto> ToList<TDto>() => ToList(GetToListDtoSelector<TDto>());
|
||||||
@ -177,89 +184,6 @@ namespace FreeSql.Internal.CommonProvider
|
|||||||
_tables[0].Parameter ?? Expression.Parameter(typeof(T1), "a"));
|
_tables[0].Parameter ?? Expression.Parameter(typeof(T1), "a"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#region linq to sql
|
|
||||||
public ISelect<TReturn> Select<TReturn>(Expression<Func<T1, TReturn>> select) where TReturn : class
|
|
||||||
{
|
|
||||||
if (typeof(TReturn) == typeof(T1)) return this as ISelect<TReturn>;
|
|
||||||
_tables[0].Parameter = select.Parameters[0];
|
|
||||||
_selectExpression = select.Body;
|
|
||||||
if (_orm.CodeFirst.IsAutoSyncStructure)
|
|
||||||
(_orm.CodeFirst as CodeFirstProvider)._dicSycedTryAdd(typeof(TReturn)); //._dicSyced.TryAdd(typeof(TReturn), true);
|
|
||||||
var ret = _orm.Select<TReturn>();
|
|
||||||
Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, null);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
public ISelect<TResult> Join<TInner, TKey, TResult>(ISelect<TInner> inner, Expression<Func<T1, TKey>> outerKeySelector, Expression<Func<TInner, TKey>> innerKeySelector, Expression<Func<T1, TInner, TResult>> resultSelector) where TInner : class where TResult : class
|
|
||||||
{
|
|
||||||
_tables[0].Parameter = resultSelector.Parameters[0];
|
|
||||||
_commonExpression.ExpressionLambdaToSql(outerKeySelector, new CommonExpression.ExpTSC { _tables = _tables });
|
|
||||||
this.InternalJoin(Expression.Lambda<Func<T1, TInner, bool>>(
|
|
||||||
Expression.Equal(outerKeySelector.Body, innerKeySelector.Body),
|
|
||||||
new[] { outerKeySelector.Parameters[0], innerKeySelector.Parameters[0] }
|
|
||||||
), SelectTableInfoType.InnerJoin);
|
|
||||||
if (typeof(TResult) == typeof(T1)) return this as ISelect<TResult>;
|
|
||||||
_selectExpression = resultSelector.Body;
|
|
||||||
if (_orm.CodeFirst.IsAutoSyncStructure)
|
|
||||||
(_orm.CodeFirst as CodeFirstProvider)._dicSycedTryAdd(typeof(TResult)); //._dicSyced.TryAdd(typeof(TResult), true);
|
|
||||||
var ret = _orm.Select<TResult>() as Select1Provider<TResult>;
|
|
||||||
Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, null);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
public ISelect<TResult> GroupJoin<TInner, TKey, TResult>(ISelect<TInner> inner, Expression<Func<T1, TKey>> outerKeySelector, Expression<Func<TInner, TKey>> innerKeySelector, Expression<Func<T1, ISelect<TInner>, TResult>> resultSelector) where TInner : class where TResult : class
|
|
||||||
{
|
|
||||||
_tables[0].Parameter = resultSelector.Parameters[0];
|
|
||||||
_commonExpression.ExpressionLambdaToSql(outerKeySelector, new CommonExpression.ExpTSC { _tables = _tables });
|
|
||||||
this.InternalJoin(Expression.Lambda<Func<T1, TInner, bool>>(
|
|
||||||
Expression.Equal(outerKeySelector.Body, innerKeySelector.Body),
|
|
||||||
new[] { outerKeySelector.Parameters[0], innerKeySelector.Parameters[0] }
|
|
||||||
), SelectTableInfoType.InnerJoin);
|
|
||||||
if (typeof(TResult) == typeof(T1)) return this as ISelect<TResult>;
|
|
||||||
_selectExpression = resultSelector.Body;
|
|
||||||
if (_orm.CodeFirst.IsAutoSyncStructure)
|
|
||||||
(_orm.CodeFirst as CodeFirstProvider)._dicSycedTryAdd(typeof(TResult)); //._dicSyced.TryAdd(typeof(TResult), true);
|
|
||||||
var ret = _orm.Select<TResult>() as Select1Provider<TResult>;
|
|
||||||
Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, null);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
public ISelect<TResult> SelectMany<TCollection, TResult>(Expression<Func<T1, ISelect<TCollection>>> collectionSelector, Expression<Func<T1, TCollection, TResult>> resultSelector) where TCollection : class where TResult : class
|
|
||||||
{
|
|
||||||
SelectTableInfo find = null;
|
|
||||||
if (collectionSelector.Body.NodeType == ExpressionType.Call)
|
|
||||||
{
|
|
||||||
var callExp = collectionSelector.Body as MethodCallExpression;
|
|
||||||
if (callExp.Method.Name == "DefaultIfEmpty" && callExp.Object.Type.GetGenericArguments().Any())
|
|
||||||
{
|
|
||||||
find = _tables.Where((a, idx) => idx > 0 && a.Type == SelectTableInfoType.InnerJoin && a.Table.Type == callExp.Object.Type.GetGenericArguments()[0]).LastOrDefault();
|
|
||||||
if (find != null)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(find.On)) find.On = Regex.Replace(find.On, $@"\b{find.Alias}\.", $"{resultSelector.Parameters[1].Name}.");
|
|
||||||
if (!string.IsNullOrEmpty(find.NavigateCondition)) find.NavigateCondition = Regex.Replace(find.NavigateCondition, $@"\b{find.Alias}\.", $"{resultSelector.Parameters[1].Name}.");
|
|
||||||
find.Type = SelectTableInfoType.LeftJoin;
|
|
||||||
find.Alias = resultSelector.Parameters[1].Name;
|
|
||||||
find.Parameter = resultSelector.Parameters[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (find == null)
|
|
||||||
{
|
|
||||||
var tb = _commonUtils.GetTableByEntity(typeof(TCollection));
|
|
||||||
if (tb == null) throw new Exception($"SelectMany 错误的类型:{typeof(TCollection).FullName}");
|
|
||||||
_tables.Add(new SelectTableInfo { Alias = resultSelector.Parameters[1].Name, AliasInit = resultSelector.Parameters[1].Name, Parameter = resultSelector.Parameters[1], Table = tb, Type = SelectTableInfoType.From });
|
|
||||||
}
|
|
||||||
if (typeof(TResult) == typeof(T1)) return this as ISelect<TResult>;
|
|
||||||
_selectExpression = resultSelector.Body;
|
|
||||||
if (_orm.CodeFirst.IsAutoSyncStructure)
|
|
||||||
(_orm.CodeFirst as CodeFirstProvider)._dicSycedTryAdd(typeof(TResult)); //._dicSyced.TryAdd(typeof(TResult), true);
|
|
||||||
var ret = _orm.Select<TResult>() as Select1Provider<TResult>;
|
|
||||||
Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, null);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
public ISelect<T1> DefaultIfEmpty()
|
|
||||||
{
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
public DataTable ToDataTable<TReturn>(Expression<Func<T1, TReturn>> select)
|
public DataTable ToDataTable<TReturn>(Expression<Func<T1, TReturn>> select)
|
||||||
{
|
{
|
||||||
if (select == null) return this.InternalToDataTable(select?.Body);
|
if (select == null) return this.InternalToDataTable(select?.Body);
|
||||||
@ -1083,8 +1007,6 @@ namespace FreeSql.Internal.CommonProvider
|
|||||||
_trackToList?.Invoke(list);
|
_trackToList?.Invoke(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IQueryable<T1> AsQueryable() => new QueryableProvider<T1>(this);
|
|
||||||
|
|
||||||
#if net40
|
#if net40
|
||||||
#else
|
#else
|
||||||
async internal Task SetListAsync(IEnumerable<T1> list)
|
async internal Task SetListAsync(IEnumerable<T1> list)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using FreeSql.Internal.Model;
|
using FreeSql.Internal.Model;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
@ -9,14 +10,15 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace FreeSql.Internal.CommonProvider
|
namespace FreeSql.Internal.CommonProvider
|
||||||
{
|
{
|
||||||
public class SelectGroupingProvider<TKey, TValue> : ISelectGrouping<TKey, TValue>
|
public class SelectGroupingProvider
|
||||||
{
|
{
|
||||||
internal IFreeSql _orm;
|
public IFreeSql _orm;
|
||||||
internal object _select;
|
public object _select;
|
||||||
internal ReadAnonymousTypeInfo _map;
|
public ReadAnonymousTypeInfo _map;
|
||||||
internal string _field;
|
public string _field;
|
||||||
internal CommonExpression _comonExp;
|
public CommonExpression _comonExp;
|
||||||
internal List<SelectTableInfo> _tables;
|
public List<SelectTableInfo> _tables;
|
||||||
|
|
||||||
public SelectGroupingProvider(IFreeSql orm, object select, ReadAnonymousTypeInfo map, string field, CommonExpression comonExp, List<SelectTableInfo> tables)
|
public SelectGroupingProvider(IFreeSql orm, object select, ReadAnonymousTypeInfo map, string field, CommonExpression comonExp, List<SelectTableInfo> tables)
|
||||||
{
|
{
|
||||||
_orm = orm;
|
_orm = orm;
|
||||||
@ -27,7 +29,7 @@ namespace FreeSql.Internal.CommonProvider
|
|||||||
_tables = tables;
|
_tables = tables;
|
||||||
}
|
}
|
||||||
|
|
||||||
string getSelectGroupingMapString(Expression[] members)
|
public string getSelectGroupingMapString(Expression[] members)
|
||||||
{
|
{
|
||||||
if (members.Any() == false) return _map.DbField;
|
if (members.Any() == false) return _map.DbField;
|
||||||
var parentName = ((members.FirstOrDefault() as MemberExpression)?.Expression as MemberExpression)?.Member.Name;
|
var parentName = ((members.FirstOrDefault() as MemberExpression)?.Expression as MemberExpression)?.Member.Name;
|
||||||
@ -85,59 +87,45 @@ namespace FreeSql.Internal.CommonProvider
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ISelectGrouping<TKey, TValue> Having(Expression<Func<ISelectGroupingAggregate<TKey, TValue>, bool>> exp)
|
public void InternalHaving(Expression exp)
|
||||||
{
|
{
|
||||||
var sql = _comonExp.ExpressionWhereLambda(null, exp, getSelectGroupingMapString, null, null);
|
var sql = _comonExp.ExpressionWhereLambda(null, exp, getSelectGroupingMapString, null, null);
|
||||||
var method = _select.GetType().GetMethod("Having", new[] { typeof(string), typeof(object) });
|
var method = _select.GetType().GetMethod("Having", new[] { typeof(string), typeof(object) });
|
||||||
method.Invoke(_select, new object[] { sql, null });
|
method.Invoke(_select, new object[] { sql, null });
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
public void InternalOrderBy(Expression exp, bool isDescending)
|
||||||
public ISelectGrouping<TKey, TValue> OrderBy<TMember>(Expression<Func<ISelectGroupingAggregate<TKey, TValue>, TMember>> column)
|
|
||||||
{
|
{
|
||||||
var sql = _comonExp.ExpressionWhereLambda(null, column, getSelectGroupingMapString, null, null);
|
var sql = _comonExp.ExpressionWhereLambda(null, exp, getSelectGroupingMapString, null, null);
|
||||||
var method = _select.GetType().GetMethod("OrderBy", new[] { typeof(string), typeof(object) });
|
var method = _select.GetType().GetMethod("OrderBy", new[] { typeof(string), typeof(object) });
|
||||||
method.Invoke(_select, new object[] { sql, null });
|
method.Invoke(_select, new object[] { isDescending ? $"{sql} DESC" : sql, null });
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
public object InternalToList(Expression select, Type elementType, bool isAsync)
|
||||||
public ISelectGrouping<TKey, TValue> OrderByDescending<TMember>(Expression<Func<ISelectGroupingAggregate<TKey, TValue>, TMember>> column)
|
|
||||||
{
|
|
||||||
var sql = _comonExp.ExpressionWhereLambda(null, column, getSelectGroupingMapString, null, null);
|
|
||||||
var method = _select.GetType().GetMethod("OrderBy", new[] { typeof(string), typeof(object) });
|
|
||||||
method.Invoke(_select, new object[] { $"{sql} DESC", null });
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<TReturn> Select<TReturn>(Expression<Func<ISelectGroupingAggregate<TKey, TValue>, TReturn>> select) => ToList(select);
|
|
||||||
public List<TReturn> ToList<TReturn>(Expression<Func<ISelectGroupingAggregate<TKey, TValue>, TReturn>> select)
|
|
||||||
{
|
{
|
||||||
var map = new ReadAnonymousTypeInfo();
|
var map = new ReadAnonymousTypeInfo();
|
||||||
var field = new StringBuilder();
|
var field = new StringBuilder();
|
||||||
var index = 0;
|
var index = 0;
|
||||||
|
|
||||||
_comonExp.ReadAnonymousField(null, field, map, ref index, select, getSelectGroupingMapString, null, false);
|
_comonExp.ReadAnonymousField(null, field, map, ref index, select, getSelectGroupingMapString, null, false);
|
||||||
if (map.Childs.Any() == false && map.MapType == null) map.MapType = typeof(TReturn);
|
if (map.Childs.Any() == false && map.MapType == null) map.MapType = elementType;
|
||||||
var method = _select.GetType().GetMethod("ToListMapReader", BindingFlags.Instance | BindingFlags.NonPublic);
|
var method = _select.GetType().GetMethod(isAsync ? "ToListMapReaderAsync" : "ToListMapReader", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||||
method = method.MakeGenericMethod(typeof(TReturn));
|
method = method.MakeGenericMethod(elementType);
|
||||||
return method.Invoke(_select, new object[] { new ReadAnonymousTypeAfInfo(map, field.Length > 0 ? field.Remove(0, 2).ToString() : null) }) as List<TReturn>;
|
return method.Invoke(_select, new object[] { new ReadAnonymousTypeAfInfo(map, field.Length > 0 ? field.Remove(0, 2).ToString() : null) });
|
||||||
}
|
}
|
||||||
public Dictionary<TKey, TElement> ToDictionary<TElement>(Expression<Func<ISelectGroupingAggregate<TKey, TValue>, TElement>> elementSelector)
|
public IEnumerable<KeyValuePair<object, object>> InternalToKeyValuePairs(Expression elementSelector, Type elementType)
|
||||||
{
|
{
|
||||||
var map = new ReadAnonymousTypeInfo();
|
var map = new ReadAnonymousTypeInfo();
|
||||||
var field = new StringBuilder();
|
var field = new StringBuilder();
|
||||||
var index = 0;
|
var index = 0;
|
||||||
|
|
||||||
_comonExp.ReadAnonymousField(null, field, map, ref index, elementSelector, getSelectGroupingMapString, null, false);
|
_comonExp.ReadAnonymousField(null, field, map, ref index, elementSelector, getSelectGroupingMapString, null, false);
|
||||||
if (map.Childs.Any() == false && map.MapType == null) map.MapType = typeof(TElement);
|
if (map.Childs.Any() == false && map.MapType == null) map.MapType = elementType;
|
||||||
var method = _select.GetType().GetMethod("ToListMapReaderPrivate", BindingFlags.Instance | BindingFlags.NonPublic);
|
var method = _select.GetType().GetMethod("ToListMapReaderPrivate", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||||
method = method.MakeGenericMethod(typeof(TElement));
|
method = method.MakeGenericMethod(elementType);
|
||||||
var otherAf = new ReadAnonymousTypeOtherInfo(_field, _map, new List<object>());
|
var otherAf = new ReadAnonymousTypeOtherInfo(_field, _map, new List<object>());
|
||||||
var values = method.Invoke(_select, new object[] { new ReadAnonymousTypeAfInfo(map, field.Length > 0 ? field.Remove(0, 2).ToString() : null), new[] { otherAf } }) as List<TElement>;
|
var values = method.Invoke(_select, new object[] { new ReadAnonymousTypeAfInfo(map, field.Length > 0 ? field.Remove(0, 2).ToString() : null), new[] { otherAf } }) as IList;
|
||||||
return otherAf.retlist.Select((a, b) => new KeyValuePair<TKey, TElement>((TKey)a, values[b])).ToDictionary(a => a.Key, a => a.Value);
|
return otherAf.retlist.Select((a, b) => new KeyValuePair<object, object>(a, values[b]));
|
||||||
}
|
}
|
||||||
|
public string InternalToSql(Expression select, FieldAliasOptions fieldAlias = FieldAliasOptions.AsIndex)
|
||||||
public string ToSql<TReturn>(Expression<Func<ISelectGroupingAggregate<TKey, TValue>, TReturn>> select, FieldAliasOptions fieldAlias = FieldAliasOptions.AsIndex)
|
|
||||||
{
|
{
|
||||||
var map = new ReadAnonymousTypeInfo();
|
var map = new ReadAnonymousTypeInfo();
|
||||||
var field = new StringBuilder();
|
var field = new StringBuilder();
|
||||||
@ -147,6 +135,14 @@ namespace FreeSql.Internal.CommonProvider
|
|||||||
var method = _select.GetType().GetMethod("ToSql", new[] { typeof(string) });
|
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;
|
return method.Invoke(_select, new object[] { field.Length > 0 ? field.Remove(0, 2).ToString() : null }) as string;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SelectGroupingProvider<TKey, TValue> : SelectGroupingProvider, ISelectGrouping<TKey, TValue>
|
||||||
|
{
|
||||||
|
public SelectGroupingProvider(IFreeSql orm, object select, ReadAnonymousTypeInfo map, string field, CommonExpression comonExp, List<SelectTableInfo> tables)
|
||||||
|
:base(orm, select, map, field, comonExp, tables) { }
|
||||||
|
|
||||||
|
public string ToSql<TReturn>(Expression<Func<ISelectGroupingAggregate<TKey, TValue>, TReturn>> select, FieldAliasOptions fieldAlias = FieldAliasOptions.AsIndex) => InternalToSql(select, fieldAlias);
|
||||||
public string ToSql(string field)
|
public string ToSql(string field)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(field))
|
if (string.IsNullOrEmpty(field))
|
||||||
@ -163,7 +159,6 @@ namespace FreeSql.Internal.CommonProvider
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public ISelectGrouping<TKey, TValue> Offset(int offset) => this.Skip(offset);
|
public ISelectGrouping<TKey, TValue> Offset(int offset) => this.Skip(offset);
|
||||||
|
|
||||||
public ISelectGrouping<TKey, TValue> Limit(int limit)
|
public ISelectGrouping<TKey, TValue> Limit(int limit)
|
||||||
{
|
{
|
||||||
var method = _select.GetType().GetMethod("Limit", new[] { typeof(int) });
|
var method = _select.GetType().GetMethod("Limit", new[] { typeof(int) });
|
||||||
@ -171,7 +166,6 @@ namespace FreeSql.Internal.CommonProvider
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public ISelectGrouping<TKey, TValue> Take(int limit) => this.Limit(limit);
|
public ISelectGrouping<TKey, TValue> Take(int limit) => this.Limit(limit);
|
||||||
|
|
||||||
public ISelectGrouping<TKey, TValue> Page(int pageNumber, int pageSize)
|
public ISelectGrouping<TKey, TValue> Page(int pageNumber, int pageSize)
|
||||||
{
|
{
|
||||||
var method = _select.GetType().GetMethod("Page", new[] { typeof(int), typeof(int) });
|
var method = _select.GetType().GetMethod("Page", new[] { typeof(int), typeof(int) });
|
||||||
@ -186,22 +180,31 @@ namespace FreeSql.Internal.CommonProvider
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ISelectGrouping<TKey, TValue> Having(Expression<Func<ISelectGroupingAggregate<TKey, TValue>, bool>> exp)
|
||||||
|
{
|
||||||
|
InternalHaving(exp);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public ISelectGrouping<TKey, TValue> OrderBy<TMember>(Expression<Func<ISelectGroupingAggregate<TKey, TValue>, TMember>> column)
|
||||||
|
{
|
||||||
|
InternalOrderBy(column, false);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public ISelectGrouping<TKey, TValue> OrderByDescending<TMember>(Expression<Func<ISelectGroupingAggregate<TKey, TValue>, TMember>> column)
|
||||||
|
{
|
||||||
|
InternalOrderBy(column, true);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<TReturn> Select<TReturn>(Expression<Func<ISelectGroupingAggregate<TKey, TValue>, TReturn>> select) => ToList(select);
|
||||||
|
public List<TReturn> ToList<TReturn>(Expression<Func<ISelectGroupingAggregate<TKey, TValue>, TReturn>> select) => InternalToList(select, typeof(TReturn), false) as List<TReturn>;
|
||||||
|
public Dictionary<TKey, TElement> ToDictionary<TElement>(Expression<Func<ISelectGroupingAggregate<TKey, TValue>, TElement>> elementSelector) => InternalToKeyValuePairs(elementSelector, typeof(TElement)).ToDictionary(a => (TKey)a.Key, a => (TElement)a.Value);
|
||||||
|
|
||||||
#if net40
|
#if net40
|
||||||
#else
|
#else
|
||||||
async public Task<long> CountAsync() => long.TryParse(string.Concat(await _orm.Ado.ExecuteScalarAsync($"select count(1) from ({this.ToSql($"1{_comonExp._common.FieldAsAlias("as1")}")}) fta")), out var trylng) ? trylng : default(long);
|
async public Task<long> CountAsync() => long.TryParse(string.Concat(await _orm.Ado.ExecuteScalarAsync($"select count(1) from ({this.ToSql($"1{_comonExp._common.FieldAsAlias("as1")}")}) fta")), out var trylng) ? trylng : default(long);
|
||||||
|
|
||||||
public Task<List<TReturn>> ToListAsync<TReturn>(Expression<Func<ISelectGroupingAggregate<TKey, TValue>, TReturn>> select)
|
public Task<List<TReturn>> ToListAsync<TReturn>(Expression<Func<ISelectGroupingAggregate<TKey, TValue>, TReturn>> select) => InternalToList(select, typeof(TReturn), true) as Task<List<TReturn>>;
|
||||||
{
|
|
||||||
var map = new ReadAnonymousTypeInfo();
|
|
||||||
var field = new StringBuilder();
|
|
||||||
var index = 0;
|
|
||||||
|
|
||||||
_comonExp.ReadAnonymousField(null, field, map, ref index, select, getSelectGroupingMapString, null, false);
|
|
||||||
if (map.Childs.Any() == false && map.MapType == null) map.MapType = typeof(TReturn);
|
|
||||||
var method = _select.GetType().GetMethod("ToListMapReaderAsync", BindingFlags.Instance | BindingFlags.NonPublic);
|
|
||||||
method = method.MakeGenericMethod(typeof(TReturn));
|
|
||||||
return method.Invoke(_select, new object[] { new ReadAnonymousTypeAfInfo(map, field.Length > 0 ? field.Remove(0, 2).ToString() : null) }) as Task<List<TReturn>>;
|
|
||||||
}
|
|
||||||
async public Task<Dictionary<TKey, TElement>> ToDictionaryAsync<TElement>(Expression<Func<ISelectGroupingAggregate<TKey, TValue>, TElement>> elementSelector)
|
async public Task<Dictionary<TKey, TElement>> ToDictionaryAsync<TElement>(Expression<Func<ISelectGroupingAggregate<TKey, TValue>, TElement>> elementSelector)
|
||||||
{
|
{
|
||||||
var map = new ReadAnonymousTypeInfo();
|
var map = new ReadAnonymousTypeInfo();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user