Create API in Remote.Linq.EntityFrameworkCore to get query result without mapping to DynamicObject
Hello/ Thanks for great lib. Can you add API in Remote.Linq.EntityFrameworkCore to get query result without mapping to DynamicObject?
In my case i need to handle query result before send to a client. Now i have to convert dynamic object to an target object, and than convert it back to DynamicObject. I think its excess overhead.
May be:
//var resp = await expression.ExecuteWithEntityFrameworkCoreAsync(ctx, HttpContext.RequestAborted);
var obj = await expression.ResultWithEntityFrameworkCoreAsync(ctx, HttpContext.RequestAborted);
// .. some work with obj
return new Aqua.Dynamic.DynamicObjectMapper().MapObject(obj);
Edit:
In addition, add useful API for get IQueryable object for manual prepare (Some limitations, mutations)
-
There are various method overloads allowing to provide a
Func<Type, IQueryable> queryableProviderargument in place of aDbContext, which allows using custom logic to to resolve and amend theIQueryableto be used. -
These extension methods also exist as generic variants, which return the result as the original result type. For working with various types,
objectcan be specified as generic argument. E.g.object result = await expression.ExecuteWithEntityFrameworkCoreAsync<object>(ctx) -
For further customization of query execution, you may want to update to RL v7.3.0-alpha-001 and either create your own "execution decorator" or make use of the "fluent API". Either way, you have the option of returning data converted into
DynamicObjector any other data type of your choice by specifying a generic type argument accordingly.
Fluent API
return await expression.EntityFrameworkCoreExecutor(efContext)
.With(PrepareRemoteLinqExpressionStrategy)
.With(PrepareSystemLinqExpressionStrategy)
.With(ProcessExecutionResultsStrategy)
.With(ProcessDynamicObjectResultsStrategy)
.ExecuteAsync(cancellation);
static Remote.Linq.Expressions.Expression PrepareRemoteLinqExpressionStrategy(Remote.Linq.Expressions.Expression exp)
=> exp;
static System.Linq.Expressions.Expression PrepareSystemLinqExpressionStrategy(System.Linq.Expressions.Expression exp)
=> exp;
static object ProcessExecutionResultsStrategy(object result)
=> result;
static DynamicObject ProcessDynamicObjectResultsStrategy(DynamicObject result)
=> result;
Execution Decorator
var executor = expression.EntityFrameworkCoreExecutor(efContext);
var decorator = new CustomExpressionExecutionDecorator(executor);
return await decorator.ExecuteAsync(cancellationToken);
private sealed class CustomExpressionExecutionDecorator : AsyncExpressionExecutionContext<DynamicObject>
{
public CustomExpressionExecutionDecorator(AsyncExpressionExecutionContext<DynamicObject> parent)
: base(parent)
{
}
protected override Expression Prepare(Expression expression)
{
// used for synchronous and asynchronous execution
return base.Prepare(expression);
}
protected override System.Linq.Expressions.Expression Transform(Expression expression)
{
// used for synchronous and asynchronous execution
return base.Transform(expression);
}
protected override System.Linq.Expressions.Expression Prepare(System.Linq.Expressions.Expression expression)
{
// used for synchronous and asynchronous execution
return base.Prepare(expression);
}
protected override System.Linq.Expressions.Expression PrepareAsyncQuery(System.Linq.Expressions.Expression expression, CancellationToken cancellation)
{
// used for asynchronous execution only
return base.PrepareAsyncQuery(expression, cancellation);
}
protected override object Execute(System.Linq.Expressions.Expression expression)
{
// used for synchronous execution only
return base.Execute(expression);
}
protected override ValueTask<object> ExecuteAsync(System.Linq.Expressions.Expression expression, CancellationToken cancellation)
{
// used for asynchronous execution only
return base.ExecuteAsync(expression, cancellation);
}
protected override object ProcessResult(object queryResult)
{
// used for synchronous and asynchronous execution
return base.ProcessResult(queryResult);
}
protected override DynamicObject ConvertResult(object queryResult)
{
// used for synchronous and asynchronous execution
return base.ConvertResult(queryResult);
}
protected override DynamicObject ProcessConvertedResult(DynamicObject queryResult)
{
// used for synchronous and asynchronous execution
return base.ProcessConvertedResult(queryResult);
}
}
Cool, thank s. It will resolve my case and more
I am delighted with the capabilities of this library in conjunction with the Blazor web assembly. I have implemented data requests almost to the end. This mechanism should experimentally replace GraphQL with the exception of database modification operations. It remains for security purposes to get an IQueryable object associated with the DbContext for some restrictive manipulations (for example, the data output limit)