/// <inheritdoc/> public IQueryable CreateQuery(SystemLinq.Expression expression) { var elementType = TypeHelper.GetElementType(expression.CheckNotNull(nameof(expression)).Type) ?? throw new RemoteLinqException($"Failed to get element type of {expression.Type}"); return(new RemoteQueryable(elementType, this, expression)); }
public RemoteLinq.Expression ToRemoteExpression(SystemLinq.Expression expression) { var partialEvalExpression = expression.CheckNotNull(nameof(expression)).PartialEval(_canBeEvaluatedLocally); var constExpression = Visit(partialEvalExpression); return(constExpression.Unwrap()); }
/// <summary> /// Executes the <see cref="SystemLinq.Expression"/> and returns the raw result. /// </summary> /// <remarks> /// <see cref="InvalidOperationException"/> get handled for failing /// <see cref="Queryable.Single{TSource}(IQueryable{TSource})"/> and /// <see cref="Queryable.Single{TSource}(IQueryable{TSource}, SystemLinq.Expression{Func{TSource, bool}})"/>, /// <see cref="Queryable.First{TSource}(IQueryable{TSource})"/>, /// <see cref="Queryable.First{TSource}(IQueryable{TSource}, SystemLinq.Expression{Func{TSource, bool}})"/>, /// <see cref="Queryable.Last{TSource}(IQueryable{TSource})"/>, /// <see cref="Queryable.Last{TSource}(IQueryable{TSource}, SystemLinq.Expression{Func{TSource, bool}})"/>. /// Instead of throwing an exception, an array with the length of zero respectively two elements is returned. /// </remarks> /// <param name="expression">The <see cref="SystemLinq.Expression"/> to be executed.</param> /// <returns>Execution result of the <see cref="SystemLinq.Expression"/> specified.</returns> protected virtual object?Execute(SystemLinq.Expression expression) { expression.CheckNotNull(nameof(expression)); try { return(ExecuteCore(expression)); } catch (InvalidOperationException ex) { if (string.Equals(ex.Message, "Sequence contains no elements", StringComparison.Ordinal)) { return(Array.CreateInstance(expression.Type, 0)); } if (string.Equals(ex.Message, "Sequence contains no matching element", StringComparison.Ordinal)) { return(Array.CreateInstance(expression.Type, 0)); } if (string.Equals(ex.Message, "Sequence contains more than one element", StringComparison.Ordinal)) { return(Array.CreateInstance(expression.Type, 2)); } if (string.Equals(ex.Message, "Sequence contains more than one matching element", StringComparison.Ordinal)) { return(Array.CreateInstance(expression.Type, 2)); } throw; } }
/// <summary> /// Executes the <see cref="SystemLinq.Expression"/> and returns the raw result. /// </summary> /// <param name="expression">The <see cref="SystemLinq.Expression"/> to be executed.</param> /// <param name="cancellation">A <see cref="CancellationToken" /> to observe while waiting for the task to complete.</param> /// <returns>Execution result of the <see cref="SystemLinq.Expression"/> specified.</returns> protected override async ValueTask <object?> ExecuteCoreAsync(SystemLinq.Expression expression, CancellationToken cancellation) { cancellation.ThrowIfCancellationRequested(); var queryResult = expression.CheckNotNull(nameof(expression)).CompileAndInvokeExpression(); if (queryResult is not null && queryResult.GetType().Implements(typeof(ValueTask <>), out var genericArguments)) { var m = typeof(ValueTask <>).MakeGenericType(genericArguments !).GetMethodEx(nameof(ValueTask <int> .AsTask)); queryResult = m.Invoke(queryResult, null); } if (queryResult is Task task) { if (!expression.Type.Implements(typeof(Task <>), out var resultType)) { resultType = task .GetType() .GetGenericArguments() .ToArray(); } if (resultType.Length != 1) { throw new RemoteLinqException($"Failed to retrieve the result type for async query result {task.GetType()}"); } try { queryResult = await GetTaskResultAsync(task, resultType[0]).ConfigureAwait(false); } catch (InvalidOperationException ex) { // workarround for issue https://github.com/dotnet/efcore/issues/18742 (relevant for ef core prior version 5.0) if (string.Equals(ex.Message, "Enumerator failed to MoveNextAsync.", StringComparison.Ordinal)) { throw new InvalidOperationException("Sequence contains no elements", ex); } throw; } } if (queryResult is null) { return(null); } cancellation.ThrowIfCancellationRequested(); if (queryResult is IQueryable queryable) { // force query execution task = Helper.ToListAsync(queryable, cancellation); queryResult = await GetTaskResultAsync(task, typeof(List <>).MakeGenericType(queryable.ElementType)).ConfigureAwait(false); } return(queryResult); }
protected override IAsyncEnumerable <object?> ExecuteAsyncStream(SystemLinq.Expression expression, CancellationToken cancellation) { if (!expression.CheckNotNull(nameof(expression)).Type.Implements(typeof(IQueryable <>))) { throw new ArgumentException("Expression must be of type IQueryable<>", nameof(expression)); } var queryable = (IQueryable)expression.CompileAndInvokeExpression() !; return(queryable.ExecuteAsAsyncStreamWithCancellation(cancellation)); }
/// <summary> /// Executes the <see cref="SystemLinq.Expression"/> and returns the raw result. /// </summary> /// <param name="expression">The <see cref="SystemLinq.Expression"/> to be executed.</param> /// <param name="cancellation">A <see cref="CancellationToken" /> to observe while waiting for the task to complete.</param> /// <returns>Execution result of the <see cref="SystemLinq.Expression"/> specified.</returns> protected override async ValueTask <object?> ExecuteCoreAsync(SystemLinq.Expression expression, CancellationToken cancellation) { cancellation.ThrowIfCancellationRequested(); var queryResult = expression.CheckNotNull(nameof(expression)).CompileAndInvokeExpression(); if (queryResult is not null && queryResult.GetType().Implements(typeof(ValueTask <>), out var genericArguments)) { var m = typeof(ValueTask <>).MakeGenericType(genericArguments).GetMethodEx(nameof(ValueTask <int> .AsTask)); queryResult = m.Invoke(queryResult, null); } if (queryResult is Task task) { if (!expression.Type.Implements(typeof(Task <>), out var resultType)) { resultType = task .GetType() .GetGenericArguments() .ToArray(); } if (resultType.Length != 1) { throw new RemoteLinqException($"Failed to retrieve the result type for async query result {task.GetType()}"); } queryResult = await GetTaskResultAsync(task, resultType[0]).ConfigureAwait(false); } if (queryResult is null) { return(null); } cancellation.ThrowIfCancellationRequested(); if (queryResult is IQueryable queryable) { // force query execution task = Helper.ToListAsync(queryable, cancellation); queryResult = await GetTaskResultAsync(task, typeof(List <>).MakeGenericType(queryable.ElementType)).ConfigureAwait(false); } return(queryResult); }
/// <summary> /// Executes the <see cref="SystemLinq.Expression"/> and returns the raw result. /// </summary> /// <param name="expression">The <see cref="SystemLinq.Expression"/> to be executed.</param> /// <returns>Execution result of the <see cref="SystemLinq.Expression"/> specified.</returns> protected static object?ExecuteCore(SystemLinq.Expression expression) { var queryResult = expression.CheckNotNull(nameof(expression)).CompileAndInvokeExpression(); if (queryResult is null) { return(null); } var queryableType = queryResult.GetType(); if (queryableType.Implements(typeof(IQueryable <>), out var genericType)) { // force query execution queryResult = MethodInfos.Enumerable.ToArray.MakeGenericMethod(genericType[0]).InvokeAndUnwrap(null, queryResult); } return(queryResult); }
/// <summary> /// 检查测试信息信息是否存在 /// </summary> /// <param name="predicate">检查谓语表达式</param> /// <param name="id">更新的测试信息编号</param> /// <returns>测试信息是否存在</returns> public bool CheckTestInfoExists(Expression<Func<TestInfo, bool>> predicate, int id = 0) { predicate.CheckNotNull("predicate"); return TestInfoRepository.CheckExists(predicate, id); }
/// <summary> /// 以 Expression.OrElse 组合两个Expression表达式 /// </summary> /// <typeparam name="T">表达式的主实体类型</typeparam> /// <param name="first">第一个Expression表达式</param> /// <param name="second">要组合的Expression表达式</param> /// <returns>组合后的表达式</returns> public static Expression <Func <T, bool> > Or <T>(this Expression <Func <T, bool> > first, Expression <Func <T, bool> > second) { first.CheckNotNull("first"); second.CheckNotNull("second"); return(first.Compose(second, Expression.OrElse)); }