6bee / remote.linq Goto Github PK
View Code? Open in Web Editor NEWSimply LINQ your remote resources...
License: MIT License
Simply LINQ your remote resources...
License: MIT License
There is an issue in deserializing serialized expressions with nested and multiple parameters as shown in the following code snippet. It gives the "Argument types don't match" error. We used "Remote.Linq 5.6.1" and "Newtonsoft.Json 11.0.2", and we tried both ".net46" and ".netcoreapp2.0" target frameworks.
class Program
{
static void Main(string[] args)
{
Expression<Func<int, Dataset<int, string>>> expr = n => new Dataset<int, string>(new DataShard<int, string>(n), 5);
var closureEliminator = new ClosureEliminator();
Expression visitedExpr = closureEliminator.Visit(expr);
var serializedExpr = SerializationHelper.Serialize(visitedExpr);
var outputExpr = SerializationHelper.Deserialize(serializedExpr);
}
}
public class Dataset<TKey, TPayload>
{
public Dataset() { }
public Dataset(DataShard<TKey, TPayload> shard, int x) : this() { }
}
public class DataShard<TKey, TPayload>
{
public DataShard(){ }
public DataShard(int n) : this(){ }
}
public class SerializationHelper
{
private SerializationHelper() { }
private static readonly JsonSerializerSettings _serializerSettings
= new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto,
NullValueHandling = NullValueHandling.Ignore,
TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Full,
};
internal static string Serialize(Expression expression)
{
var toSerialize = expression.ToRemoteLinqExpression()
.ReplaceGenericQueryArgumentsByNonGenericArguments();
return JsonConvert.SerializeObject(toSerialize, _serializerSettings);
}
internal static Expression Deserialize(string expression)
{
var deserialized = JsonConvert.DeserializeObject<Remote.Linq.Expressions.LambdaExpression>(
expression, _serializerSettings);
var ret = deserialized.ReplaceNonGenericQueryArgumentsByGenericArguments().ToLinqExpression();
return ret;
}
}
public class ClosureEliminator : System.Linq.Expressions.ExpressionVisitor
{
protected override Expression VisitMember(MemberExpression node)
{
if ((node.Expression != null) && (node.Expression.NodeType == ExpressionType.Constant))
{
object target = ((ConstantExpression)node.Expression).Value, value;
switch (node.Member.MemberType)
{
case System.Reflection.MemberTypes.Property:
value = ((System.Reflection.PropertyInfo)node.Member).GetValue(target, null);
break;
case System.Reflection.MemberTypes.Field:
value = ((System.Reflection.FieldInfo)node.Member).GetValue(target);
break;
default:
value = target = null;
break;
}
if (target != null)
{
if (value.GetType().IsSubclassOf(typeof(Expression)))
{
return this.Visit(value as Expression);
}
else
{
return Expression.Constant(value, node.Type);
}
}
}
return base.VisitMember(node);
}
}
public struct ObjectWrapper
{
public string type;
public string data;
}
Hi, I have System.StackOverflowException when I call ToRemoteLinqExpression. Can you help me?
var func = new Func<A, bool>(wagons => wagons.Number > 0);
Expression<Func<A, bool>> exp = x => func(x);
var a = exp.ToRemoteLinqExpression();
public class A {
public int Number { get; set; }
}
Hi Christof,
We just stumbled across your ntieref library, and we're excited about using it. However, we noticed that no new builds have been posted in over 2 years (1.9), and the "Issues" tab has been closed down.
Is the ntieref still active? Also, are there any other middle-tier libraries like the ntieref that we should be considering using? We're being forced by our server team NOT to connect directly with our SQL Server from our externally facing ASP.NET MVC application,, so we need a middle-tier app server, but really love the convenience offered by your ntieref library.
Thanks in advance!
5.5.0-beta-001
_productQueryable
.Select(p => new {ids = _productQueryable.Select(pp => pp.Id)})
.Select(a => a.ids.Count())
.ToList();
fails with
System.InvalidOperationException
variable 'a' of type '<>f__AnonymousType1`1[System.Linq.IQueryable`1[System.Int32]]' referenced from scope '', but it is not defined
at System.Linq.Expressions.Compiler.VariableBinder.Reference(ParameterExpression node, VariableStorageKind storage)
at System.Linq.Expressions.Compiler.VariableBinder.VisitParameter(ParameterExpression node)
at System.Linq.Expressions.ExpressionVisitor.VisitMember(MemberExpression node)
at System.Linq.Expressions.ExpressionVisitor.Visit(ReadOnlyCollection`1 nodes)
at System.Linq.Expressions.Compiler.VariableBinder.VisitLambda[T](Expression`1 node)
at System.Linq.Expressions.Compiler.LambdaCompiler.Compile(LambdaExpression lambda, DebugInfoGenerator debugInfoGenerator)
at System.Linq.Expressions.Expression`1.Compile()
at Remote.Linq.ExpressionVisitors.SystemExpressionReWriter.RemoteQueryableVisitor.VisitMemberAccess(MemberExpression node)
at Remote.Linq.ExpressionVisitors.ExpressionVisitorBase.Visit(Expression expression)
at Remote.Linq.ExpressionVisitors.ExpressionVisitorBase.VisitExpressionList[T](ReadOnlyCollection`1 original)
at Remote.Linq.ExpressionVisitors.ExpressionVisitorBase.VisitMethodCall(MethodCallExpression node)
at Remote.Linq.ExpressionVisitors.ExpressionVisitorBase.Visit(Expression expression)
at Remote.Linq.ExpressionVisitors.ExpressionVisitorBase.VisitLambda(LambdaExpression node)
at Remote.Linq.ExpressionVisitors.ExpressionVisitorBase.Visit(Expression expression)
at Remote.Linq.ExpressionVisitors.ExpressionVisitorBase.VisitUnary(UnaryExpression node)
at Remote.Linq.ExpressionVisitors.ExpressionVisitorBase.Visit(Expression expression)
at Remote.Linq.ExpressionVisitors.ExpressionVisitorBase.VisitExpressionList[T](ReadOnlyCollection`1 original)
at Remote.Linq.ExpressionVisitors.ExpressionVisitorBase.VisitMethodCall(MethodCallExpression node)
at Remote.Linq.ExpressionVisitors.ExpressionVisitorBase.Visit(Expression expression)
at Remote.Linq.ExpressionVisitors.SystemExpressionReWriter.RemoteQueryableVisitor.Simplify(Expression expression)
at Remote.Linq.ExpressionVisitors.SystemExpressionReWriter.SimplifyIncorporationOfRemoteQueryables(Expression expression)
at Remote.Linq.DynamicQuery.RemoteQueryProvider`1.TranslateExpression(Expression expression, ITypeResolver typeResolver)
at Remote.Linq.DynamicQuery.RemoteQueryProvider`1.Execute[TResult](Expression expression)
at Remote.Linq.DynamicQuery.RemoteQueryable`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
Add the following test to Remote.Linq.Tests.RemoteQueryable.When_running_query
class
[Fact]
public void Should_return_orders_joined_with_chars()
{
char[] array = { 'h', 'e', 'l', 'l', 'o' };
var joinLocalVariable = (
from i in _orderItemQueriable
from s in array
select new { i, s }
).ToList();
var joinNewArrayInit = (
from i in _orderItemQueriable
from s in new[] { 'h', 'e', 'l', 'l', 'o' }
select new { i, s }
).ToList();
var joinConst = (
from i in _orderItemQueriable
from s in "hello"
select new { i, s }
).ToList();
}
The first two queries work fine, but the last one fails with
Result Message: Expression of type 'System.Func`2[Remote.Linq.Tests.RemoteQueryable.TestData.OrderItem,System.String]' cannot be used for parameter of type 'System.Linq.Expressions.Expression`1[System.Func`2[Remote.Linq.Tests.RemoteQueryable.TestData.OrderItem,System.Collections.Generic.IEnumerable`1[System.Char]]]' of method 'System.Linq.IQueryable`1[<>f__AnonymousType3`2[Remote.Linq.Tests.RemoteQueryable.TestData.OrderItem,System.Char]] SelectMany[OrderItem,Char,<>f__AnonymousType3`2](System.Linq.IQueryable`1[Remote.Linq.Tests.RemoteQueryable.TestData.OrderItem], System.Linq.Expressions.Expression`1[System.Func`2[Remote.Linq.Tests.RemoteQueryable.TestData.OrderItem,System.Collections.Generic.IEnumerable`1[System.Char]]], System.Linq.Expressions.Expression`1[System.Func`3[Remote.Linq.Tests.RemoteQueryable.TestData.OrderItem,System.Char,<>f__AnonymousType3`2[Remote.Linq.Tests.RemoteQueryable.TestData.OrderItem,System.Char]]])'
Result StackTrace:
at System.Linq.Expressions.Expression.ValidateOneArgument(MethodBase method, ExpressionType nodeKind, Expression arg, ParameterInfo pi)
at System.Linq.Expressions.Expression.ValidateArgumentTypes(MethodBase method, ExpressionType nodeKind, ReadOnlyCollection`1& arguments)
at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, IEnumerable`1 arguments)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitMethodCall(MethodCallExpression methodCallExpression) in D:\remotelinq\src\Remote.Linq\ExpressionVisitors\ExpressionTranslator.cs:line 868
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression) in D:\remotelinq\src\Remote.Linq\ExpressionVisitors\ExpressionTranslator.cs:line 618
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.ToExpression(Expression expression) in D:\remotelinq\src\Remote.Linq\ExpressionVisitors\ExpressionTranslator.cs:line 583
at Remote.Linq.ExpressionTranslator.ToLinqExpression(Expression expression, ITypeResolver typeResolver) in D:\remotelinq\src\Remote.Linq\ExpressionVisitors\ExpressionTranslator.cs:line 79
at Remote.Linq.Expressions.ExpressionExtensions.PrepareForExecution(Expression expression, Func`2 queryableProvider, ITypeResolver typeResolver) in D:\remotelinq\src\Remote.Linq\Expressions\ExpressionExtensions.cs:line 153
at Remote.Linq.Expressions.ExpressionExtensions.Execute(Expression expression, Func`2 queryableProvider, ITypeResolver typeResolver, Func`2 resultPorjector, IDynamicObjectMapper mapper, Func`2 setTypeInformation) in D:\remotelinq\src\Remote.Linq\Expressions\ExpressionExtensions.cs:line 89
at Remote.Linq.Tests.RemoteQueryable.When_running_query.<>c__DisplayClass3_0.<.ctor>b__2(Expression x) in D:\remotelinq\test\Remote.Linq.Tests\RemoteQueryable\When_running_query.cs:line 22
at Remote.Linq.DynamicQuery.RemoteQueryProvider`1.Execute[TResult](Expression expression) in D:\remotelinq\src\Remote.Linq\DynamicQuery\RemoteQueryProvider`.cs:line 43
at Remote.Linq.DynamicQuery.RemoteQueryable`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator() in D:\remotelinq\src\Remote.Linq\DynamicQuery\RemoteQueryable`.cs:line 22
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at Remote.Linq.Tests.RemoteQueryable.When_running_query.Should_return_orders_joined_with_chars() in D:\remotelinq\test\Remote.Linq.Tests\RemoteQueryable\When_running_query.cs:line 100
This example may look a bit constructed, but unfortunately we are getting the same error in more practical situations when the LINQ expression is built dynamically, e.g. from the Remotion.Linq model. The expression builder (over which we have no control) is emitting a ConstantExpression(fixed_array)
for the join, which causes ToLinqExpression
to fail.
I did a bit of debugging and it seems like in the first two queries the arrays are wrapped as VariableQueryArgumentList whilst in the third case the constant is passed literally.
DataContractSerializer
fails on both queries
_categoryQueryable.Select(c => new { i = 123 }).ToList();
int x = 123;
_categoryQueryable.Select(c => new { i = x }).ToList();
System.Runtime.Serialization.InvalidDataContractException : Type '<>f__AnonymousType5`1[System.Int32]' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. If the type is a collection, consider marking it with the CollectionDataContractAttribute. See the Microsoft .NET Framework documentation for other supported types.
Test Should_query_product_categories_filterd_using_inline_enum
fails if I replace ==
with .Equals
[Fact]
public void Should_query_product_categories_filterd_using_EQUALS_inline_enum()
{
var query =
from c in _categoryQueryable
where c.CategoryType.Equals(CategoryType.NonFood)
select c;
var result = query.ToArray();
result.Count().ShouldBe(1);
}
System.ArgumentException : Argument types do not match
StackTrace:
at System.Linq.Expressions.Expression.Constant(Object value, Type type)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitConstant(ConstantExpression constantValueExpression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitUnary(UnaryExpression unaryExpression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.<VisitMethodCall>b__20_0(Expression x)
at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitMethodCall(MethodCallExpression methodCallExpression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitLambda(LambdaExpression lambdaExpression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitUnary(UnaryExpression unaryExpression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.<VisitMethodCall>b__20_0(Expression x)
at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitMethodCall(MethodCallExpression methodCallExpression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.ToExpression(Expression expression)
at Remote.Linq.ExpressionTranslator.ToLinqExpression(Expression expression, ITypeResolver typeResolver)
at Remote.Linq.Expressions.ExpressionExtensions.PrepareForExecution(Expression expression, Func`2 queryableProvider, ITypeResolver typeResolver)
at Remote.Linq.Expressions.ExpressionExtensions.Execute(Expression expression, Func`2 queryableProvider, ITypeResolver typeResolver, Func`2 resultPorjector, IDynamicObjectMapper mapper, Func`2 setTypeInformation)
at Remote.Linq.Tests.RemoteQueryable.When_running_query.<>c__DisplayClass9_1.<.ctor>b__0(Expression expression)
at Remote.Linq.DynamicQuery.RemoteQueryProvider`1.Execute[TResult](Expression expression)
at Remote.Linq.DynamicQuery.RemoteQueryable`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator()
at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
at Remote.Linq.Tests.RemoteQueryable.When_running_query.Should_query_product_categories_filterd_using_inline_enum()
In our scenarios we observed the same error with .HasFlag
instead of .Equals
for bit-field enums, but I believe the nature of the bug should be the same?
There exist scenarios like dotnet/efcore#5445 where filter conditions are built dynamically using Expression.Lambda/Expression.Invoke. Apparently those aren't yet fully supported by Remote.Linq-5.5.0-beta-002.
System.Linq.Expressions.Expression<Func<Category, bool>> expression = c => c.Name == "hello";
var parameter = System.Linq.Expressions.Expression.Parameter(typeof(Category), "c");
_categoryQueryable.Where(
System.Linq.Expressions.Expression.Lambda<Func<Category, bool>>(
System.Linq.Expressions.Expression.Invoke(expression, parameter), parameter)).ToList();
fails with
System.ArgumentException
Expression of type 'Remote.Linq.Expressions.LambdaExpression' cannot be invoked
at System.Linq.Expressions.Expression.GetInvokeMethod(Expression expression)
at System.Linq.Expressions.Expression.Invoke(Expression expression, IEnumerable`1 arguments)
at Remote.Linq.ExpressionVisitors.ExpressionVisitorBase.VisitInvocation(InvocationExpression node)
at Remote.Linq.ExpressionVisitors.ExpressionVisitorBase.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.LinqExpressionToRemoteExpressionTranslator.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.LinqExpressionToRemoteExpressionTranslator.VisitLambda(LambdaExpression node)
at Remote.Linq.ExpressionVisitors.ExpressionVisitorBase.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.LinqExpressionToRemoteExpressionTranslator.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.LinqExpressionToRemoteExpressionTranslator.VisitUnary(UnaryExpression node)
at Remote.Linq.ExpressionVisitors.ExpressionVisitorBase.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.LinqExpressionToRemoteExpressionTranslator.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.LinqExpressionToRemoteExpressionTranslator.<VisitMethodCall>b__24_0(Expression argument)
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at Remote.Linq.Expressions.MethodCallExpression..ctor(Expression insatnce, MethodInfo methodInfo, IEnumerable`1 arguments)
at Remote.Linq.Expressions.MethodCallExpression..ctor(Expression insatnce, MethodInfo methodInfo, IEnumerable`1 arguments)
at Remote.Linq.ExpressionTranslator.LinqExpressionToRemoteExpressionTranslator.VisitMethodCall(MethodCallExpression node)
at Remote.Linq.ExpressionVisitors.ExpressionVisitorBase.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.LinqExpressionToRemoteExpressionTranslator.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.LinqExpressionToRemoteExpressionTranslator.ToRemoteExpression(Expression expression)
at Remote.Linq.ExpressionTranslator.ToRemoteLinqExpression(Expression expression)
at Remote.Linq.DynamicQuery.RemoteQueryProvider`1.TranslateExpression(Expression expression, ITypeResolver typeResolver)
at Remote.Linq.DynamicQuery.RemoteQueryProvider`1.Execute[TResult](Expression expression)
at Remote.Linq.DynamicQuery.RemoteQueryable`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
When trying to get this working (possibly incorrectly), if the EF connection of the context for a CodeFirst setup is left in the default behavior (open, exec, close) an exception is thrown: The connection is not open.
why, I do not know, it's expecting the connection to be opened for it, so I go ahead and do that, I manually open the connection and it results in a stack overflow:
using Aqua.Dynamic;
using log4net;
using Remote.Linq.Expressions;
using System.Collections.Generic;
namespace Project.Repo.Repo
{
public class RemoteQueryRepo : BaseRepo, IRemoteQueryRepo
{
private readonly ILog _log4Net;
public RemoteQueryRepo()
{
_log4Net = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
}
public IEnumerable<DynamicObject> RemoteQuery(Expression expression)
{
Db.Database.Connection.Open();
return expression.Execute(queryableProvider: (type) => Db.GetQueryableByType(type));
}
}
}
System.Core.dll!System.Linq.Enumerable.CombinePredicates.AnonymousMethod__0(System.__Canon x) Unknown
System.Core.dll!System.Linq.Enumerable.WhereArrayIterator<System.Reflection.PropertyInfo>.MoveNext() Unknown
Aqua.dll!Aqua.Dynamic.DynamicObjectMapper.PopulateObjectMembers(System.Type type, object from, Aqua.Dynamic.DynamicObject to, System.Func<System.Type, bool> setTypeInformation) Unknown
Aqua.dll!Aqua.Dynamic.DynamicObjectMapper.ToContext.TryGetOrCreateNew(System.Type sourceType, object from, System.Func<System.Type, object, System.Func<System.Type, bool>, Aqua.Dynamic.DynamicObject> factory, System.Action<System.Type, object, Aqua.Dynamic.DynamicObject, System.Func<System.Type, bool>> initializer, System.Func<System.Type, bool> setTypeInformation) Unknown
Aqua.dll!Aqua.Dynamic.DynamicObjectMapper.MapInternal(object obj, System.Func<System.Type, bool> setTypeInformation) Unknown
Remote.Linq.dll!Remote.Linq.DynamicQuery.DynamicQueryResultMapper.MapToDynamicObjectGraph(object obj, System.Func<System.Type, bool> setTypeInformation) Unknown
Aqua.dll!Aqua.Dynamic.DynamicObjectMapper.MapToDynamicObjectIfRequired(object obj, System.Func<System.Type, bool> setTypeInformation) Unknown
Aqua.dll!Aqua.Dynamic.DynamicObjectMapper.PopulateObjectMembers(System.Type type, object from, Aqua.Dynamic.DynamicObject to, System.Func<System.Type, bool> setTypeInformation) Unknown
Aqua.dll!Aqua.Dynamic.DynamicObjectMapper.ToContext.TryGetOrCreateNew(System.Type sourceType, object from, System.Func<System.Type, object, System.Func<System.Type, bool>, Aqua.Dynamic.DynamicObject> factory, System.Action<System.Type, object, Aqua.Dynamic.DynamicObject, System.Func<System.Type, bool>> initializer, System.Func<System.Type, bool> setTypeInformation) Unknown
Aqua.dll!Aqua.Dynamic.DynamicObjectMapper.MapInternal(object obj, System.Func<System.Type, bool> setTypeInformation) Unknown
Remote.Linq.dll!Remote.Linq.DynamicQuery.DynamicQueryResultMapper.MapToDynamicObjectGraph(object obj, System.Func<System.Type, bool> setTypeInformation) Unknown
Aqua.dll!Aqua.Dynamic.DynamicObjectMapper.MapToDynamicObjectIfRequired(object obj, System.Func<System.Type, bool> setTypeInformation) Unknown
Aqua.dll!Aqua.Dynamic.DynamicObjectMapper.MapToDynamicObjectIfRequired.AnonymousMethod__0(object x) Unknown
System.Core.dll!System.Linq.Enumerable.WhereSelectEnumerableIterator<object, object>.MoveNext() Unknown
System.Core.dll!System.Linq.Buffer<object>.Buffer(System.Collections.Generic.IEnumerable<object> source) Unknown
System.Core.dll!System.Linq.Enumerable.ToArray<object>(System.Collections.Generic.IEnumerable<object> source) Unknown
Aqua.dll!Aqua.Dynamic.DynamicObjectMapper.MapToDynamicObjectIfRequired(object obj, System.Func<System.Type, bool> setTypeInformation) Unknown
Aqua.dll!Aqua.Dynamic.DynamicObjectMapper.PopulateObjectMembers(System.Type type, object from, Aqua.Dynamic.DynamicObject to, System.Func<System.Type, bool> setTypeInformation) Unknown
Aqua.dll!Aqua.Dynamic.DynamicObjectMapper.ToContext.TryGetOrCreateNew(System.Type sourceType, object from, System.Func<System.Type, object, System.Func<System.Type, bool>, Aqua.Dynamic.DynamicObject> factory, System.Action<System.Type, object, Aqua.Dynamic.DynamicObject, System.Func<System.Type, bool>> initializer, System.Func<System.Type, bool> setTypeInformation) Unknown
Aqua.dll!Aqua.Dynamic.DynamicObjectMapper.MapInternal(object obj, System.Func<System.Type, bool> setTypeInformation) Unknown
Remote.Linq.dll!Remote.Linq.DynamicQuery.DynamicQueryResultMapper.MapToDynamicObjectGraph(object obj, System.Func<System.Type, bool> setTypeInformation) Unknown
Aqua.dll!Aqua.Dynamic.DynamicObjectMapper.MapToDynamicObjectIfRequired(object obj, System.Func<System.Type, bool> setTypeInformation) Unknown
Aqua.dll!Aqua.Dynamic.DynamicObjectMapper.PopulateObjectMembers(System.Type type, object from, Aqua.Dynamic.DynamicObject to, System.Func<System.Type, bool> setTypeInformation) Unknown
Aqua.dll!Aqua.Dynamic.DynamicObjectMapper.ToContext.TryGetOrCreateNew(System.Type sourceType, object from, System.Func<System.Type, object, System.Func<System.Type, bool>, Aqua.Dynamic.DynamicObject> factory, System.Action<System.Type, object, Aqua.Dynamic.DynamicObject, System.Func<System.Type, bool>> initializer, System.Func<System.Type, bool> setTypeInformation) Unknown
Aqua.dll!Aqua.Dynamic.DynamicObjectMapper.MapInternal(object obj, System.Func<System.Type, bool> setTypeInformation) Unknown
Remote.Linq.dll!Remote.Linq.DynamicQuery.DynamicQueryResultMapper.MapToDynamicObjectGraph(object obj, System.Func<System.Type, bool> setTypeInformation) Unknown
Aqua.dll!Aqua.Dynamic.DynamicObjectMapper.MapToDynamicObjectIfRequired(object obj, System.Func<System.Type, bool> setTypeInformation) Unknown
Aqua.dll!Aqua.Dynamic.DynamicObjectMapper.MapToDynamicObjectIfRequired.AnonymousMethod__0(object x) Unknown
System.Core.dll!System.Linq.Enumerable.WhereSelectEnumerableIterator<object, object>.MoveNext() Unknown
System.Core.dll!System.Linq.Buffer<object>.Buffer(System.Collections.Generic.IEnumerable<object> source) Unknown
System.Core.dll!System.Linq.Enumerable.ToArray<object>(System.Collections.Generic.IEnumerable<object> source) Unknown
Aqua.dll!Aqua.Dynamic.DynamicObjectMapper.MapToDynamicObjectIfRequired(object obj, System.Func<System.Type, bool> setTypeInformation) Unknown
Aqua.dll!Aqua.Dynamic.DynamicObjectMapper.PopulateObjectMembers(System.Type type, object from, Aqua.Dynamic.DynamicObject to, System.Func<System.Type, bool> setTypeInformation) Unknown
Aqua.dll!Aqua.Dynamic.DynamicObjectMapper.ToContext.TryGetOrCreateNew(System.Type sourceType, object from, System.Func<System.Type, object, System.Func<System.Type, bool>, Aqua.Dynamic.DynamicObject> factory, System.Action<System.Type, object, Aqua.Dynamic.DynamicObject, System.Func<System.Type, bool>> initializer, System.Func<System.Type, bool> setTypeInformation) Unknown
Aqua.dll!Aqua.Dynamic.DynamicObjectMapper.MapInternal(object obj, System.Func<System.Type, bool> setTypeInformation) Unknown
Remote.Linq.dll!Remote.Linq.DynamicQuery.DynamicQueryResultMapper.MapToDynamicObjectGraph(object obj, System.Func<System.Type, bool> setTypeInformation) Unknown
Aqua.dll!Aqua.Dynamic.DynamicObjectMapper.MapToDynamicObjectIfRequired(object obj, System.Func<System.Type, bool> setTypeInformation) Unknown
Aqua.dll!Aqua.Dynamic.DynamicObjectMapper.PopulateObjectMembers(System.Type type, object from, Aqua.Dynamic.DynamicObject to, System.Func<System.Type, bool> setTypeInformation) Unknown
Aqua.dll!Aqua.Dynamic.DynamicObjectMapper.ToContext.TryGetOrCreateNew(System.Type sourceType, object from, System.Func<System.Type, object, System.Func<System.Type, bool>, Aqua.Dynamic.DynamicObject> factory, System.Action<System.Type, object, Aqua.Dynamic.DynamicObject, System.Func<System.Type, bool>> initializer, System.Func<System.Type, bool> setTypeInformation) Unknown
Aqua.dll!Aqua.Dynamic.DynamicObjectMapper.MapInternal(object obj, System.Func<System.Type, bool> setTypeInformation) Unknown
I extended When_using_dynamic_object_for_complex_object_tree
class with one more test
public class When_using_dynamic_object_for_complex_object_tree
{
// ...
public When_using_dynamic_object_for_complex_object_tree()
{
var originalObject = new DynamicObject()
{
{ "DoubleValue", DoubleValue },
{
"Reference", new DynamicObject(typeof(string))
{
{ "StringValue", StringValue },
}
},
};
serializedObject = originalObject.Serialize();
}
[Fact]
public void Clone_should_contain_type_information()
{
var nestedObject = serializedObject["Reference"] as DynamicObject;
(nestedObject.Type?.Type).ShouldBe(typeof(string));
}
// ...
}
It passes with BinaryFormatter
, DataContractSerializer
and NetDataContractSerializer
, but fails with JsonSerializer
and XmlSerializer
.
Test Should_query_products_filterd_using_local_variables_closure_inline_mix
fails if I pass a list of Ids as queryable
[Fact]
public void Should_query_products_filterd_using_local_variables_closure_inline_mix()
{
IEnumerable<int?> listOfIds = new List<int?>() { null, 1, 11, 111 }.AsQueryable(); // <=== EnumerableQuery
int oneId = 10;
var query =
from p in _productQueryable
where listOfIds.Contains(p.Id) || new List<string> { "Truck", "Bicycle" }.Contains(p.Name) || p.Id % 3 == 0 || p.Id == oneId
select p;
var result = query.ToArray();
result.Count().ShouldBe(4);
}
System.Collections.Generic.KeyNotFoundException
The given key was not present in the dictionary.
at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
at Remote.Linq.Tests.RemoteQueryable.QueryTestData.Store.Get(Type type)
at Remote.Linq.ExpressionVisitors.QueryableResourceVisitor.ResourceDescriptorVisitor.VisitConstant(ConstantExpression expression)
at Remote.Linq.ExpressionVisitors.RemoteExpressionVisitorBase.Visit(Expression expression)
at Remote.Linq.ExpressionVisitors.RemoteExpressionVisitorBase.VisitExpressionList(List`1 original)
at Remote.Linq.ExpressionVisitors.RemoteExpressionVisitorBase.VisitNew(NewExpression newExpression)
at Remote.Linq.ExpressionVisitors.RemoteExpressionVisitorBase.Visit(Expression expression)
at Remote.Linq.ExpressionVisitors.RemoteExpressionVisitorBase.VisitMemberAccess(MemberExpression expression)
at Remote.Linq.ExpressionVisitors.RemoteExpressionVisitorBase.Visit(Expression expression)
at Remote.Linq.ExpressionVisitors.RemoteExpressionVisitorBase.<VisitMethodCall>b__22_0(Expression i)
at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at Remote.Linq.ExpressionVisitors.RemoteExpressionVisitorBase.VisitMethodCall(MethodCallExpression expression)
at Remote.Linq.ExpressionVisitors.RemoteExpressionVisitorBase.Visit(Expression expression)
at Remote.Linq.ExpressionVisitors.RemoteExpressionVisitorBase.VisitBinary(BinaryExpression expression)
at Remote.Linq.ExpressionVisitors.RemoteExpressionVisitorBase.Visit(Expression expression)
at Remote.Linq.ExpressionVisitors.RemoteExpressionVisitorBase.VisitBinary(BinaryExpression expression)
at Remote.Linq.ExpressionVisitors.RemoteExpressionVisitorBase.Visit(Expression expression)
at Remote.Linq.ExpressionVisitors.RemoteExpressionVisitorBase.VisitBinary(BinaryExpression expression)
at Remote.Linq.ExpressionVisitors.RemoteExpressionVisitorBase.Visit(Expression expression)
at Remote.Linq.ExpressionVisitors.RemoteExpressionVisitorBase.VisitLambda(LambdaExpression expression)
at Remote.Linq.ExpressionVisitors.RemoteExpressionVisitorBase.Visit(Expression expression)
at Remote.Linq.ExpressionVisitors.RemoteExpressionVisitorBase.VisitUnary(UnaryExpression expression)
at Remote.Linq.ExpressionVisitors.RemoteExpressionVisitorBase.Visit(Expression expression)
at Remote.Linq.ExpressionVisitors.RemoteExpressionVisitorBase.<VisitMethodCall>b__22_0(Expression i)
at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at Remote.Linq.ExpressionVisitors.RemoteExpressionVisitorBase.VisitMethodCall(MethodCallExpression expression)
at Remote.Linq.ExpressionVisitors.RemoteExpressionVisitorBase.Visit(Expression expression)
at Remote.Linq.ExpressionVisitors.QueryableResourceVisitor.ResourceDescriptorVisitor.ReplaceResourceDescriptorsByQueryable(Expression expression)
at Remote.Linq.ExpressionVisitors.QueryableResourceVisitor.ReplaceResourceDescriptorsByQueryable[T](T expression, Func`2 provider, ITypeResolver typeResolver)
at Remote.Linq.ExpressionVisitors.RemoteExpressionReWriter.ReplaceResourceDescriptorsByQueryable[T](T expression, ITypeResolver typeResolver, Func`2 provider)
at Remote.Linq.Expressions.ExpressionExtensions.PrepareForExecution(Expression expression, Func`2 queryableProvider, ITypeResolver typeResolver)
at Remote.Linq.Expressions.ExpressionExtensions.Execute(Expression expression, Func`2 queryableProvider, ITypeResolver typeResolver, Func`2 resultPorjector, IDynamicObjectMapper mapper, Func`2 setTypeInformation)
at Remote.Linq.Tests.RemoteQueryable.When_running_query.<>c__DisplayClass9_1.<.ctor>b__0(Expression expression)
at Remote.Linq.DynamicQuery.RemoteQueryProvider`1.Execute[TResult](Expression expression)
at Remote.Linq.DynamicQuery.RemoteQueryable`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator()
at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
at Remote.Linq.Tests.RemoteQueryable.When_running_query.Should_query_products_filterd_using_local_variables_closure_inline_mix()
I think it should be sufficient to simply prevent translation of values of type System.Linq.EnumerableQuery
to QueryableResourceDescriptor
.
I am using Remote.Linqe with OData endpoint and it uses IQuerable
instead of IQuerable<T>
to build queries, but AsyncRemoteQueryable
does not have an overload for IEnumerable.GetEnumerator
so it uses the base one from RemoteQueryable
. But this implementation tries to deserialize to the IEnumerable
interface with an exception: 'Failed to pick matching constructor for type System.Collections.IEnumerable'.
Hi,
I have not been able to find a way to execute a EF6 query async on the server.
I am currently using the following in my webapi query method.
var results = query.Expression.ExecuteWithEntityFramework(Context);
I sort of expected to find ExecuteWithEntityFrameworkAsync method.
Is this something the you never got to? Maybe you did not feel it is nessesary?
I tried to use Remote.Linq client side in an asynchronous manner. I might be doing it wrong, if not then please add support for this:
public class RemoteRepository
{
private readonly Func<Expression, Task<IEnumerable<DynamicObject>>> _dataProvider;
public RemoteRepository()
{
//Func<Task<IEnumerable<DynamicObject>>> myFun = async () => await myTask;
_dataProvider = async (expression) =>
{
// setup service connectivity
//IQueryService service = new QueryService();
// send expression to service and get back results
JsonSerializerSettings serializerSettings = new JsonSerializerSettings();//.ConfigureRemoteLinq();
string json = JsonConvert.SerializeObject(expression, serializerSettings);
IEnumerable<DynamicObject> result = await API.RemoteQuery(json);
return result;
};
}
public IQueryable<Filter> Filters => RemoteQueryable.Factory.CreateQueryable<Filter>(_dataProvider);
}
Unable to cast object of type 'System.Threading.Tasks.Task`1[System.Collections.Generic.IEnumerable`1[Aqua.Dynamic.DynamicObject]]' to type 'System.Collections.Generic.IEnumerable`1[Project.Repo.Filter]'.
at Remote.Linq.DynamicQuery.ObjectResultCaster.MapResult[TResult](Object source, Expression expression)
at Remote.Linq.DynamicQuery.RemoteQueryProvider`1.Execute[TResult](Expression expression)
at Remote.Linq.DynamicQuery.RemoteQueryable`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)```
Hi!
After adding this member to my EF (6.2, code-first) entity class:
public const string MY_CONST = "Something";
I run into a FieldAccessException on the client side on composing the Linq query for remote execution thrown by the Aqua.Dynamic.DynamicObjectMapper, I tried to add the [NonSerialize]
attribute to that member but that didn't help. For the time being I changed the const into a static member and the error is gone, but that is not exactly what I want.
How can I avoid this exception or does the Aqua lib need an update?
Thanks!
Karlo
PS:
Ok, I just found that by adding the [Unmapped] attribute to the public const member I can avoid this problem. However this introduces an extra dependency (on the Aqua.dll) to my .dll that holds the EF entity classes. Wouldn't it make sense to treat const's as Unmapped anyway?
We run into another issue with dynamically built LINQ queries which contain ConstantExpression
s of type array. This time the query crashes during serialization. Similar to #4 it works fine when the array is represented by a NewArrayInitExpression
but fails when a (seemingly equivalent) ConstantExpression
is being used.
Please run the following test in the Remote.Linq.Tests.RemoteQueryable.When_running_query
class to reproduce the problem
[Fact]
public void ArrayContainsSerializationTest()
{
System.Linq.Expressions.Expression<Func<Category, bool>> lambdaNewArrayInit =
c => new[] { "Vehicles" }.Contains(c.Name);
var mc = (System.Linq.Expressions.MethodCallExpression)lambdaNewArrayInit.Body;
var lambdaConst = System.Linq.Expressions.Expression.Lambda<Func<Category, bool>>(
System.Linq.Expressions.Expression.Call(
mc.Method,
System.Linq.Expressions.Expression.Constant(new[] { "Vehicles" }),
mc.Arguments[1]),
lambdaNewArrayInit.Parameters);
_categoryQueriable.Where(lambdaNewArrayInit).ToList(); // [PASS]
_categoryQueriable.Where(lambdaConst).ToList(); // [FAIL]
}
System.Runtime.Serialization.SerializationException : Type 'System.String[]' with data contract name 'ArrayOfstring:http://schemas.microsoft.com/2003/10/Serialization/Arrays' is not expected. Consider using a DataContractResolver if you are using DataContractSerializer or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to the serializer.
And again it seems to have something to do with NOT using VariableQueryArgumentList
in the second query.
According to msdn one can create a System.Linq.Expressions.ParameterExpression
without ParameterName
. However in Remote.Linq.Expressions.ParameterExpression
it is marked as required, which leads to JsonSerializationException : Required property 'ParameterName' not found in JSON
during deserialization.
Hello, I am trying to use SingleOrDefaultAsync
method and it fails when nothing was found.
example code in unit tests
[Fact]
public void Should_query_single_or_default_with_predicate()
{
var result = _queryable.SingleOrDefault(x => x.Value.ToUpper().Contains("asdfasdfasdfW"));
result.Key.ShouldBe("2");
}
Is it possible to use Remote.Linq with Windows 10 UWP respectively with Xamarin.Forms applications?
Json deserialization fails using Remote.Linq.Newtonsoft.Json 5.4.0-alpha-015
:
"The method or operation is not implemented."
at Remote.Linq.JsonConverters.ConstantExpressionJsonConverter.ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer)
Hi there,
I'm a previous user of your N-Tier library, and I really appreciated the User's Manual that you had included in the doc folder. Is there any user/developer documentation available for the Remote.Linq?
Also, this may be me not being totally familiar with how to download stuff from GitHub, but the only way to download that I know of is by clicking on the "Clone or Download" button while viewing the root of the repository. Unfortunately, when I download and unzip that file, it doesn't include the test folder where the samples are. Once I drill down into the folders, downloading is only available one file at a time.
Thank you in advance for your response.
Since UWP10 support was withdrawn from netstandard1.6
we should aim to add support for UWP explicitely: target platform uap10.0
see .NET Standard Versions table
var dt = new DateTimeOffset();
System.Linq.Expressions.Expression<Func<bool, DateTimeOffset>> expression = x => dt;
var remoteExpression = expression.ToRemoteLinqExpression();
var serializedRemoteExpression = DataContractSerializationHelper.Serialize(remoteExpression);
fails with SerializationException
Type 'System.Runtime.Serialization.DateTimeOffsetAdapter' with data contract name 'DateTimeOffset:http://schemas.datacontract.org/2004/07/System' is not expected. Consider using a DataContractResolver if you are using DataContractSerializer or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to the serializer.
Following issue #20 we should try and add support for LabelExpression
and GotoExpression
...
I've got a Remote Linq expression I'm trying to execute against EF like below.
Client:
string myTestValue = "MyTestValue"
var remoteQueryable = RemoteQueryable.Create<MyEntity>((exp) => QueryService(exp))
.Where(d => d.TestProperty == myTestValue);
Server:
remoteLinqExpression.Execute(t => cp.MyEntities).ToList();
which fails with 'Only parameterless constructors and initializers are supported in LINQ to Entities.'
I believe the issue is with this part of the expression tree:
System.Linq.Queryable.Where(Remote.Linq.DynamicQuery.QueryableResourceDescriptor, Quote(d => (d.SMDsym Equal New Remote.Linq.DynamicQuery.VariableQueryArgument`1{System.String}('MyTestValue').Value)))`
because if I specify a string literal, rather than the variable then it works fine.
Note this did work when using LINQ To SQL, but started failing when I moved to EF6.
Hey @6bee!
Today I finally pushed the result of about 10 months of work on my own project InfoCarrier.Core which I'm sure will interest you as well. Let me express my deepest gratitude to you for your amazing libraries Remote.Linq and aqua-core which I'm confidently relying on in my project. I would also be very thankful to you if you find a moment to have a brief look at InfoCarrier.Core and provide some feedback and fair criticism. If you wish we could arrange a Skype confo.
Best Regards,
Alexander Zabluda (aka @azabluda)
_productQueryable.Select(x => default(DateTime)).ToList(); // [PASS]
_productQueryable.Select(x => new DateTime(1,1,1)).ToList(); // [PASS]
_productQueryable.Select(x => new DateTime()).ToList(); // [FAIL] NullReferenceException
The bug b28f4a8 seems to be fixed in RemoteQueryProvider
but not yet in AsyncRemoteQueryProvider
. Could you please have a look? Thanks a lot!
Standard sample application samples\RemoteQueryable\0_Standard\Client\Demo.cs
Console.WriteLine("\nGET ALL PRODUCTS:");
foreach (var i in repo.Products)
{
Console.WriteLine(" {0} | {1} | {2:C}", i.Id, i.Name, i.Price);
}
I change the query to repo.Products.GroupBy(p => p.Id).SelectMany(g => g)
and (obviously) expect the identical results.
Unfortunately the program crashes
System.ArgumentException
Expression of type 'System.Linq.IGrouping`2[System.Int32,Common.Model.Product]' cannot be used for return type 'System.Collections.Generic.IEnumerable`1[System.Int32]'
at System.Linq.Expressions.Expression.ValidateLambdaArgs(Type delegateType, Expression& body, ReadOnlyCollection`1 parameters)
at System.Linq.Expressions.Expression.Lambda(Type delegateType, Expression body, String name, Boolean tailCall, IEnumerable`1 parameters)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitMethodCall(MethodCallExpression methodCallExpression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression)
at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitMethodCall(MethodCallExpression methodCallExpression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.ToLinqExpression(Expression expression, ITypeResolver typeResolver)
I need to work with similar but differently named objects on client and server side.
It seems that ITypeResolver
is there to solve this issue.
So I pass my implementation of ITypeResolver:
var employees = Remote.Linq.RemoteQueryable.Factory.CreateQueryable<Employee>(..., typeResolver: resultMapper: new EmployeeResolver());
However, EmployeeResolver.ResolveType
is never hit.
Hi,
the following line kills with StackOverflowException:
Expression<Func<Type>> transform = () => typeof(T); LambdaExpression expression = transform.ToRemoteLinqExpression();
I'm currently using 5.5.0 alpha 003 as I need some other features from this version. Version 5.4.1 semms to have the same issue.
Am I making some mistake?
Thanks for your help
The following test fails
var result = (
from p in _productQueryable.Take(1)
from c in _categoryQueryable.Take(1)
select new { p, c }).ToList();
result.Count().ShouldBe(1);
Shouldly.ShouldAssertException
result.Count()
should be
1
but was
2
In the debugger I can see that the second Take(1)
is gone after ToRemoteLinqExpression
.
Hello,
I use
var repo = new RemoteRepository("localhost", 8899);
var partner = await repo.Partner.ToListAsync();
dataGridView1.DataSource = partner;
In version 5.8.2, everything works fine.
In versions 6.0.0, 6.1.1 and 6.2.0 I get this error:
Process is terminated due to StackOverflowException in Remote.Linq.dll.
In these versions this example doesn't work: 10_UsingJsonSerializationOverTcpAsync.
Thank you.
Under certain conditions LinqExpressionToRemoteExpressionTranslator
reduces binary expressions to unary ones
Although it is a clever thing to do, it doesn't feel like it's an essential responsibility of Remote.Linq, since one would rather appreciate Remote.Linq's ability to deliver the original query (as close as possible) from one peer to another. Do you remember why was it necessary to implement it that way?
Second, the logic doesn't check the actual type of ConstantExpression
s. In particular it performs the reduction of expressions like SomeNullableBoolean == (bool?)true
to unary SomeNullableBoolean
which is incorrect. Here I admit it's probably only possible to run into such problem when queries are built dynamically (e.g. from Remotion.Linq model). You can try the following test in When_running_query
class
[Fact]
public void Should_handle_const_nullable_bool()
{
// [PASS]
// .Where(p => Convert(p.Name.EndsWith("x"), bool?) == Convert(True, bool?))
_productQueriable.Where(p => (bool?)p.Name.EndsWith("x") == (bool?)true).ToList();
// [FAIL]
// .Where(p => Convert(p.Name.EndsWith("x"), bool?) == Constant(True, bool?))
System.Linq.Expressions.Expression<Func<TestData.Product, bool?>> expr
= p => (bool?)p.Name.EndsWith("x");
var lambda = (System.Linq.Expressions.LambdaExpression)expr;
var predicate
= System.Linq.Expressions.Expression.Lambda<Func<TestData.Product, bool>>(
System.Linq.Expressions.Expression.Equal(
lambda.Body,
System.Linq.Expressions.Expression.Constant(true, typeof(bool?))),
lambda.Parameters);
_productQueriable.Where(predicate).ToList();
}
Result Message: Expression of type 'System.Linq.Expressions.Expression`1[System.Func`2[Remote.Linq.Tests.RemoteQueryable.TestData.Product,System.Nullable`1[System.Boolean]]]' cannot be used for parameter of type 'System.Linq.Expressions.Expression`1[System.Func`2[Remote.Linq.Tests.RemoteQueryable.TestData.Product,System.Boolean]]' of method 'System.Linq.IQueryable`1[Remote.Linq.Tests.RemoteQueryable.TestData.Product] Where[Product](System.Linq.IQueryable`1[Remote.Linq.Tests.RemoteQueryable.TestData.Product], System.Linq.Expressions.Expression`1[System.Func`2[Remote.Linq.Tests.RemoteQueryable.TestData.Product,System.Boolean]])'
Result StackTrace:
at System.Linq.Expressions.Expression.ValidateOneArgument(MethodBase method, ExpressionType nodeKind, Expression arg, ParameterInfo pi)
at System.Linq.Expressions.Expression.ValidateArgumentTypes(MethodBase method, ExpressionType nodeKind, ReadOnlyCollection`1& arguments)
at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, IEnumerable`1 arguments)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitMethodCall(MethodCallExpression methodCallExpression) in D:\remotelinq\src\Remote.Linq\ExpressionVisitors\ExpressionTranslator.cs:line 868
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression) in D:\remotelinq\src\Remote.Linq\ExpressionVisitors\ExpressionTranslator.cs:line 618
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.ToExpression(Expression expression) in D:\remotelinq\src\Remote.Linq\ExpressionVisitors\ExpressionTranslator.cs:line 583
at Remote.Linq.ExpressionTranslator.ToLinqExpression(Expression expression, ITypeResolver typeResolver) in D:\remotelinq\src\Remote.Linq\ExpressionVisitors\ExpressionTranslator.cs:line 79
at Remote.Linq.Expressions.ExpressionExtensions.PrepareForExecution(Expression expression, Func`2 queryableProvider, ITypeResolver typeResolver) in D:\remotelinq\src\Remote.Linq\Expressions\ExpressionExtensions.cs:line 153
at Remote.Linq.Expressions.ExpressionExtensions.Execute(Expression expression, Func`2 queryableProvider, ITypeResolver typeResolver, Func`2 resultPorjector, IDynamicObjectMapper mapper, Func`2 setTypeInformation) in D:\remotelinq\src\Remote.Linq\Expressions\ExpressionExtensions.cs:line 89
at Remote.Linq.Tests.RemoteQueryable.When_running_query.<>c__DisplayClass3_0.<.ctor>b__1(Expression x) in D:\remotelinq\test\Remote.Linq.Tests\RemoteQueryable\When_running_query.cs:line 22
at Remote.Linq.DynamicQuery.RemoteQueryProvider`1.Execute[TResult](Expression expression) in D:\remotelinq\src\Remote.Linq\DynamicQuery\RemoteQueryProvider`.cs:line 43
at Remote.Linq.DynamicQuery.RemoteQueryable`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator() in D:\remotelinq\src\Remote.Linq\DynamicQuery\RemoteQueryable`.cs:line 22
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at Remote.Linq.Tests.RemoteQueryable.When_running_query.Should_handle_const_nullable_bool() in D:\remotelinq\test\Remote.Linq.Tests\RemoteQueryable\When_running_query.cs:line 42
I would suggest either to remove this logic completely (if possible) or at least check the type ConstantExpression
s for bool
.
Hi!
I use a remote repository in my asp.net MVC web application to access a EF entities from another locally running backend service. The entities contain largerer blob values which are mapped to byte array members. This works like a charm, except that getting such a blob of - says - 3 MB can take a few seconds, which I think is rather long. Is this the performance I should expect? Any advice how I could identify the bottleneck or how to improve it?
Thanks!
Dependency on Newtonsoft.Json
moved from Remote.Linq
to package Remote.Linq.Newtonsoft.Json
as of version 5.4.0-alpha-017
.
To enable JSON serialization for Remote.Linq
using Newtonsoft.Json
please include Remote.Linq.Newtonsoft.Json
in your project and used the provided extension method to configure JsonSerializerSettings
:
using Newtonsoft.Json;
using Remote.Linq;
โฆ
JsonSerializerSettings serializerSettings = new JsonSerializerSettings().ConfigureRemoteLinq();
I see that you throw InvalidProviderException
on ExecuteAsync
, previously it just runs query synchronously without exception. What the purpose of this decision? I have some places which use ToArrayAsync
and for testing I just pass array.AsQueryable
and now it fails. Could you introduce a new extensions method AsRemoteAsyncQueryable
?
Would be possible to store (and load) Remote.Linq queries to (for instance) a readable text format to (from) a file ?
The two latest official releases of Remote.Linq
and aqua-core
don't always play well together. The simplest way to reproduce the problem is to check out Remote.Linq v5.8.2 and replace the following lines in test/Remote.Linq.Tests/Remote.Linq.Tests.csproj
<ItemGroup>
<ProjectReference Include="..\..\src\Remote.Linq\Remote.Linq.csproj" />
<ProjectReference Include="..\..\src\Remote.Linq.Newtonsoft.Json\Remote.Linq.Newtonsoft.Json.csproj" />
</ItemGroup>
with
<ItemGroup>
<PackageReference Include="aqua-core" Version="4.5.2" />
<PackageReference Include="Remote.Linq.Newtonsoft.Json" Version="5.8.2" />
</ItemGroup>
The two tests will fail
Test Name: Remote.Linq.Tests.RemoteQueryable.When_running_query+With_json_serializer.Should_query_anonymous_type_with_primitive_value_array_injected_as_variable_closure
Test FullName: Remote.Linq.Tests.RemoteQueryable.When_running_query+With_json_serializer.Should_query_anonymous_type_with_primitive_value_array_injected_as_variable_closure
Test Source: test\Remote.Linq.Tests\RemoteQueryable\When_running_query.cs : line 865
Test Outcome: Failed
Test Duration: 0:00:00,611
Result1 Name: Remote.Linq.Tests.RemoteQueryable.When_running_query+With_json_serializer.Should_query_anonymous_type_with_primitive_value_array_injected_as_variable_closure(type: typeof(byte[]), value: [0, 0])
Result1 Outcome: Failed
Result1 Duration: 0:00:00,003
Result1 StackTrace:
at System.Linq.Expressions.Expression.Constant(Object value, Type type)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitConstant(ConstantExpression constantValueExpression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.<VisitNew>b__10_1(Expression a)
at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Dynamic.Utils.CollectionExtensions.ToReadOnly[T](IEnumerable`1 enumerable)
at System.Linq.Expressions.Expression.New(ConstructorInfo constructor, IEnumerable`1 arguments)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitNew(NewExpression newExpression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitMember(MemberExpression memberExpression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.<VisitNew>b__10_1(Expression a)
at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Dynamic.Utils.CollectionExtensions.ToReadOnly[T](IEnumerable`1 enumerable)
at System.Linq.Expressions.Expression.New(ConstructorInfo constructor, IEnumerable`1 arguments, IEnumerable`1 members)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitNew(NewExpression newExpression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitLambda(LambdaExpression lambdaExpression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitUnary(UnaryExpression unaryExpression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.<VisitMethodCall>b__27_0(Expression x)
at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitMethodCall(MethodCallExpression methodCallExpression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression)
at Remote.Linq.Expressions.ExpressionExecutor.Transform(Expression expression)
at Remote.Linq.Expressions.ExpressionExecutor.Execute(Expression expression)
at Remote.Linq.Expressions.ExpressionExtensions.Execute(Expression expression, Func`2 queryableProvider, ITypeResolver typeResolver, IDynamicObjectMapper mapper, Func`2 setTypeInformation, Func`2 canBeEvaluatedLocally)
at Remote.Linq.Tests.RemoteQueryable.When_running_query.<>c__DisplayClass11_1.<.ctor>b__0(Expression expression) in test\Remote.Linq.Tests\RemoteQueryable\When_running_query.cs:line 80
at Remote.Linq.DynamicQuery.RemoteQueryProvider`1.Execute[TResult](Expression expression)
at Remote.Linq.DynamicQuery.RemoteQueryable`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator()
at System.Linq.Enumerable.WhereEnumerableIterator`1.MoveNext()
at System.Linq.Enumerable.Any[TSource](IEnumerable`1 source)
at Shouldly.ShouldBeEnumerableTestExtensions.ShouldAllBe[T](IEnumerable`1 actual, Expression`1 elementPredicate, Func`1 customMessage)
at Shouldly.ShouldBeEnumerableTestExtensions.ShouldAllBe[T](IEnumerable`1 actual, Expression`1 elementPredicate, String customMessage)
at Remote.Linq.Tests.RemoteQueryable.When_running_query.TestMethodFor_Should_query_anonymous_type_with_primitive_value_array_injected_as_variable_closure[T](T[] array) in test\Remote.Linq.Tests\RemoteQueryable\When_running_query.cs:line 875
Result1 Message: System.ArgumentException : Argument types do not match
Result1 StandardOutput:
Result1 StandardError:
Result2 Name: Remote.Linq.Tests.RemoteQueryable.When_running_query+With_json_serializer.Should_query_anonymous_type_with_primitive_value_array_injected_as_variable_closure(type: typeof(byte[]), value: [255, 255])
Result2 Outcome: Failed
Result2 Duration: 0:00:00,003
Result2 StackTrace:
at System.Linq.Expressions.Expression.Constant(Object value, Type type)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitConstant(ConstantExpression constantValueExpression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.<VisitNew>b__10_1(Expression a)
at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Dynamic.Utils.CollectionExtensions.ToReadOnly[T](IEnumerable`1 enumerable)
at System.Linq.Expressions.Expression.New(ConstructorInfo constructor, IEnumerable`1 arguments)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitNew(NewExpression newExpression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitMember(MemberExpression memberExpression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.<VisitNew>b__10_1(Expression a)
at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Dynamic.Utils.CollectionExtensions.ToReadOnly[T](IEnumerable`1 enumerable)
at System.Linq.Expressions.Expression.New(ConstructorInfo constructor, IEnumerable`1 arguments, IEnumerable`1 members)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitNew(NewExpression newExpression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitLambda(LambdaExpression lambdaExpression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitUnary(UnaryExpression unaryExpression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.<VisitMethodCall>b__27_0(Expression x)
at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitMethodCall(MethodCallExpression methodCallExpression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression)
at Remote.Linq.Expressions.ExpressionExecutor.Transform(Expression expression)
at Remote.Linq.Expressions.ExpressionExecutor.Execute(Expression expression)
at Remote.Linq.Expressions.ExpressionExtensions.Execute(Expression expression, Func`2 queryableProvider, ITypeResolver typeResolver, IDynamicObjectMapper mapper, Func`2 setTypeInformation, Func`2 canBeEvaluatedLocally)
at Remote.Linq.Tests.RemoteQueryable.When_running_query.<>c__DisplayClass11_1.<.ctor>b__0(Expression expression) in test\Remote.Linq.Tests\RemoteQueryable\When_running_query.cs:line 80
at Remote.Linq.DynamicQuery.RemoteQueryProvider`1.Execute[TResult](Expression expression)
at Remote.Linq.DynamicQuery.RemoteQueryable`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator()
at System.Linq.Enumerable.WhereEnumerableIterator`1.MoveNext()
at System.Linq.Enumerable.Any[TSource](IEnumerable`1 source)
at Shouldly.ShouldBeEnumerableTestExtensions.ShouldAllBe[T](IEnumerable`1 actual, Expression`1 elementPredicate, Func`1 customMessage)
at Shouldly.ShouldBeEnumerableTestExtensions.ShouldAllBe[T](IEnumerable`1 actual, Expression`1 elementPredicate, String customMessage)
at Remote.Linq.Tests.RemoteQueryable.When_running_query.TestMethodFor_Should_query_anonymous_type_with_primitive_value_array_injected_as_variable_closure[T](T[] array) in test\Remote.Linq.Tests\RemoteQueryable\When_running_query.cs:line 875
Result2 Message: System.ArgumentException : Argument types do not match
Result2 StandardOutput:
Result2 StandardError:
We are experiencing a problem Remote.Linq-ing the new EF.Functions.Like() feature, and the reason is likely that RL is translating a static property access expression to a constant instead of leaving it "as is".
I made a little repro
public class DbFunctions
{
internal DbFunctions()
{
}
public bool Like(string matchExpression, string pattern) => true;
}
public static class EF
{
public static DbFunctions Functions { get; } = new DbFunctions();
}
[Fact]
public void DbFunctionsTest()
{
var result = _productQueryable.Where(p => EF.Functions.Like(p.Name, "%")).ToList();
result.Count().ShouldBe(5);
}
System.Exception : Failed to pick matching constructor for type Remote.Linq.Tests.RemoteQueryable.When_running_query+DbFunctions
at Aqua.Dynamic.DynamicObjectMapper.MapInternal(DynamicObject obj, Type type)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitConstant(ConstantExpression constantValueExpression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.<VisitNew>b__10_1(Expression a)
at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Dynamic.Utils.CollectionExtensions.ToReadOnly[T](IEnumerable`1 enumerable)
at System.Linq.Expressions.Expression.New(ConstructorInfo constructor, IEnumerable`1 arguments)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitNew(NewExpression newExpression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitMember(MemberExpression memberExpression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitMethodCall(MethodCallExpression methodCallExpression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitLambda(LambdaExpression lambdaExpression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitUnary(UnaryExpression unaryExpression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.<VisitMethodCall>b__27_0(Expression x)
at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitMethodCall(MethodCallExpression methodCallExpression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.ToExpression(Expression expression)
at Remote.Linq.ExpressionTranslator.ToLinqExpression(Expression expression, ITypeResolver typeResolver)
at Remote.Linq.Expressions.ExpressionExtensions.PrepareForExecution(Expression expression, Func`2 queryableProvider, ITypeResolver typeResolver)
at Remote.Linq.Expressions.ExpressionExtensions.Execute(Expression expression, Func`2 queryableProvider, ITypeResolver typeResolver, Func`2 resultPorjector, IDynamicObjectMapper mapper, Func`2 setTypeInformation)
at Remote.Linq.Tests.RemoteQueryable.When_running_query.<>c__DisplayClass11_1.<.ctor>b__0(Expression expression) in D:\Projects\InfoCarrierNG\remotelinq\test\Remote.Linq.Tests\RemoteQueryable\When_running_query.cs:line 66
at Remote.Linq.DynamicQuery.RemoteQueryProvider`1.Execute[TResult](Expression expression)
at Remote.Linq.DynamicQuery.RemoteQueryable`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at Remote.Linq.Tests.RemoteQueryable.When_running_query.DbFunctionsTest()
Hi,
first Thanks for your fantanstic work.
For a project I need to Serialize an ExpressionTree that contains Expression.Block. Ist there any way I can easy extend your Translator to support this, without compiling remote linq by myself?
I have a Client Server setup where I am trying to use Remote.Linq to transfer expression from the client to the server process
and evaluate the expression on the server. I have a following simplified expression:
public class Person {
public short State { get; set; }
}
public class Client {
public BusinessLogic() {
short state = 95;
ServerCallWithFilter<Person>(p => p.State == state);
}
public ServerCallWithFilter<T>(Expression<Func<T, bool> predicate>) {
Console.WriteLine($"Predicate: {predicate}");
Remote.Linq.Expressions.LambdaExpression remoteLambda;
remoteLambda = predicate.ToRemoteLinqExpression();
Console.WriteLine($"RemoteLambda: {remoteLambda}");
// Send the predicate to the server and receive results.
}
}
When the Lambda expression is printed out it looks like this:
p => (Convert(p.State) == Convert(value(ExpressionSerialization.Program+<>c__DisplayClass1_0).state))
And the remote linq lambda looks like the following:
p => (Convert(p.State) Equal Convert(Remote.Linq.DynamicQuery.ConstantQueryArgument.state))
When the Remote.Linq LambdaExpression is passed to the server side the deserialization fails because the server side is unable to recreate the "ExpressionSerialization.Program+<>c__DisplayClass1_0" type and throws an expression.
When I change the code so the state variable is int instead of a short then Remote.Linq can replace DisplayClass with the actual value and the deserialization works on the server side:
public BusinessLogic() {
int state= 95;
ServerCallWithFilter<Person>(p => p.State == state);
}
Predicate: p => (Convert(p.State) == value(ExpressionSerialization.Program+<>c__DisplayClass1_0).state)
RemoteLambda: p => (Convert(p.State) Equal New Remote.Linq.DynamicQuery.VariableQueryArgument`1System.Int32.Value)
After debugging I noticed that whenever Remote.Linq receives an expression like Convert(value(DisplayClass).member) during evaluation it stops because of the Convert expression...
I was wondering what way this should be fixed? Is this an issue with Remote.Linq or with the Aqua library?
ConditionalExpression in the "if False"part does not work after deserialization. That is, the alternative condition "else"does not work.
How to reproduce the bug on Remote.Linq version 6.1.0 in project on .Net Core 2.2:
var condition = Expression.MakeBinary(ExpressionType.LessThan, Expression.Constant(5), Expression.Constant(2));
ConditionalExpression ifThenElseExpression = Expression.IfThenElse(
condition,
Expression.Call(
null,
typeof(Console).GetMethod("WriteLine", new Type[] { typeof(String) }),
Expression.Constant("The condition is true.")
),
Expression.Call(
null,
typeof(Console).GetMethod("WriteLine", new Type[] { typeof(String) }),
Expression.Constant("The condition is false.")
)
);
var lambdaExpression = Expression.Lambda<Action>(ifThenElseExpression);
lambdaExpression.Compile()(); // will be printed: "The condition is false."
var remote = ifThenElseExpression.ToRemoteLinqExpression();
var received = remote.ToLinqExpression();
lambdaExpression = Expression.Lambda<Action>(received);
lambdaExpression.Compile()(); // nothing will be printed :(
How to fix it or compensate?
Apparently it isn't quite impossible to have an expression with essentially different parameters sharing the same name in overlapping scopes. An interesting example can be found in EntityFrameworkCore's Where_subquery_expression_same_parametername test.
AssertQuery<Order, Order>((o1, o2) =>
{
var firstOrder = o1.First();
Expression<Func<Order, bool>> expr = x => x.OrderID == firstOrder.OrderID;
return o1.Where(x => o2.Where(expr).Where(o => o.CustomerID == x.CustomerID).Any());
});
As you correctly mentioned parameters within an expression tree must be represented by the same parameter expression instance, so the uniqueness of names isn't really necessary for LINQ.
However during LINQ => RLinq => LINQ translation you match parameters by their names which in particular messes up the a.m. query and restores a formally inequivalent LINQ from RLinq.
Is it possible translate LINQ => RLinq in such a way that distinct instances of Linq.ParameterExpression
are mapped to corresponding distinct instance of RLinq.ParameterExpression
no matter how many times a specific parameter occurs in an expression tree? Then we probably could employ the in-built capabilities of serialization frameworks (IsReference=true
) which will automatically ensure identity of RLinq.ParameterExpression
instances on the recipient end. Finally RLinq => LINQ translation should also preserve the uniqueness without having to rely on parameter names.
Having little experience with serialization frameworks I may assume that not all of them natively support IsReference=true
. Then RLinq.ParameterExpression
could just carry some InternalIdentifier
field for proper matching.
I add a simple enum property to class Remote.Linq.Tests.RemoteQueryable.QueryTestData.Product
public class Product
{
// ...
public System.ConsoleColor Color { get; set; }
}
The following queries are failing
public abstract class When_running_query
{
// ...
[Fact]
public void Should_return_all_product_using_color_filter()
{
// [FAIL] string parser for type System.ConsoleColor is not implemented
ConsoleColor red = ConsoleColor.Red;
_productQueryable.Where(p => p.Color != red).ToList();
// [FAIL] string parser for type System.Nullable`1[System.ConsoleColor] is not implemented
ConsoleColor? nullableRed = ConsoleColor.Red;
_productQueryable.Where(p => p.Color != nullableRed).ToList();
}
}
Result StackTrace:
at Aqua.Dynamic.DynamicObjectMapper.ParseToNativeType(Type targetType, String value)
at Aqua.Dynamic.DynamicObjectMapper.TryExplicitConversions(Type targetType, Object& value)
at Aqua.Dynamic.DynamicObjectMapper.<CreatePropertyInitializer>b__35_0(Type type, DynamicObject item, Object obj)
at Aqua.Dynamic.DynamicObjectMapper.ObjectFormatterContext`2.TryGetOrCreateNew(Type objectType, TFrom from, Func`3 factory, Action`3 initializer)
at Aqua.Dynamic.DynamicObjectMapper.MapInternal(DynamicObject obj, Type type)
at Aqua.Dynamic.DynamicObjectMapper.MapFromDynamicObjectIfRequired(Object obj, Type targetType)
at Aqua.Dynamic.DynamicObjectMapper.MapFromDynamicObjectGraph(Object obj, Type targetType)
at Aqua.Dynamic.DynamicObjectMapper.Map(DynamicObject obj, Type type)
at Aqua.Dynamic.DynamicObjectMapper.Map(DynamicObject obj)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitConstant(ConstantExpression constantValueExpression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitMember(MemberExpression memberExpression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitUnary(UnaryExpression unaryExpression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitBinary(BinaryExpression binaryExpression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitLambda(LambdaExpression lambdaExpression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitUnary(UnaryExpression unaryExpression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.<VisitMethodCall>b__20_0(Expression x)
at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitMethodCall(MethodCallExpression methodCallExpression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.ToExpression(Expression expression)
at Remote.Linq.ExpressionTranslator.ToLinqExpression(Expression expression, ITypeResolver typeResolver)
at Remote.Linq.Expressions.ExpressionExtensions.PrepareForExecution(Expression expression, Func`2 queryableProvider, ITypeResolver typeResolver)
at Remote.Linq.Expressions.ExpressionExtensions.Execute(Expression expression, Func`2 queryableProvider, ITypeResolver typeResolver, Func`2 resultPorjector, IDynamicObjectMapper mapper, Func`2 setTypeInformation)
at Remote.Linq.Tests.RemoteQueryable.When_running_query.<>c__DisplayClass10_1.<.ctor>b__0(Expression expression)
at Remote.Linq.DynamicQuery.RemoteQueryProvider`1.Execute[TResult](Expression expression)
at Remote.Linq.DynamicQuery.RemoteQueryable`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at Remote.Linq.Tests.RemoteQueryable.When_running_query.Should_return_all_product_using_color_filter()
Is there a particular reason that it does not have a strong name?
The following query requires two roundtrips to execute
_productQueryable.Where(p => _categoryQueryable.Any() && p.Id >= 1)
It would first evaluate _categoryQueryable.Any()
and then _productQueryable.Where(p => true && p.Id >= 1)
.
Hi,
If this project exposes dbcontext for operations on the client (it's not clear it dose so) is it secure as to what operations it allows to be performed from the deserialized linq ? Can it also do insert, update or delete ?
Thanks!
Add another test to Remote.Linq.Tests.RemoteQueryable.When_running_query
[Fact]
public void Should_return_all_product2()
{
var result = _productQueriable.Where(p => p is TestData.Product).ToList();
result.Count().ShouldBe(5);
}
Test Name: Remote.Linq.Tests.RemoteQueryable.When_running_query.Should_return_all_product2
Test FullName: Remote.Linq.Tests.RemoteQueryable.When_running_query.Should_return_all_product2
Test Source: D:\remotelinq\test\Remote.Linq.Tests\RemoteQueryable\When_running_query.cs : line 35
Test Outcome: Failed
Test Duration: 0:00:00,106
Result StackTrace:
at System.Linq.Expressions.Expression.Lambda(Expression body, String name, Boolean tailCall, IEnumerable`1 parameters)
at System.Linq.Expressions.Expression.Lambda(Expression body, ParameterExpression[] parameters)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitLambda(LambdaExpression lambdaExpression) in D:\remotelinq\src\Remote.Linq\ExpressionVisitors\ExpressionTranslator.cs:line 977
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression) in D:\remotelinq\src\Remote.Linq\ExpressionVisitors\ExpressionTranslator.cs:line 621
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitUnary(UnaryExpression unaryExpression) in D:\remotelinq\src\Remote.Linq\ExpressionVisitors\ExpressionTranslator.cs:line 774
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression) in D:\remotelinq\src\Remote.Linq\ExpressionVisitors\ExpressionTranslator.cs:line 615
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.<VisitMethodCall>b__20_0(Expression x) in D:\remotelinq\src\Remote.Linq\ExpressionVisitors\ExpressionTranslator.cs:line 808
at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.VisitMethodCall(MethodCallExpression methodCallExpression) in D:\remotelinq\src\Remote.Linq\ExpressionVisitors\ExpressionTranslator.cs:line 807
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.Visit(Expression expression) in D:\remotelinq\src\Remote.Linq\ExpressionVisitors\ExpressionTranslator.cs:line 618
at Remote.Linq.ExpressionTranslator.RemoteExpressionToLinqExpressionTranslator.ToExpression(Expression expression) in D:\remotelinq\src\Remote.Linq\ExpressionVisitors\ExpressionTranslator.cs:line 583
at Remote.Linq.ExpressionTranslator.ToLinqExpression(Expression expression, ITypeResolver typeResolver) in D:\remotelinq\src\Remote.Linq\ExpressionVisitors\ExpressionTranslator.cs:line 79
at Remote.Linq.Expressions.ExpressionExtensions.PrepareForExecution(Expression expression, Func`2 queryableProvider, ITypeResolver typeResolver) in D:\remotelinq\src\Remote.Linq\Expressions\ExpressionExtensions.cs:line 153
at Remote.Linq.Expressions.ExpressionExtensions.Execute(Expression expression, Func`2 queryableProvider, ITypeResolver typeResolver, Func`2 resultPorjector, IDynamicObjectMapper mapper, Func`2 setTypeInformation) in D:\remotelinq\src\Remote.Linq\Expressions\ExpressionExtensions.cs:line 89
at Remote.Linq.Tests.RemoteQueryable.When_running_query.<>c__DisplayClass3_0.<.ctor>b__1(Expression x) in D:\remotelinq\test\Remote.Linq.Tests\RemoteQueryable\When_running_query.cs:line 21
at Remote.Linq.DynamicQuery.RemoteQueryProvider`1.Execute[TResult](Expression expression) in D:\remotelinq\src\Remote.Linq\DynamicQuery\RemoteQueryProvider`.cs:line 43
at Remote.Linq.DynamicQuery.RemoteQueryable`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator() in D:\remotelinq\src\Remote.Linq\DynamicQuery\RemoteQueryable`.cs:line 22
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at Remote.Linq.Tests.RemoteQueryable.When_running_query.Should_return_all_product2() in D:\remotelinq\test\Remote.Linq.Tests\RemoteQueryable\When_running_query.cs:line 36
Result Message:
Value cannot be null.
Parameter name: body
Having the following code:
CaseInfo info = new CaseInfo();
CaseInfo info2 = new CaseInfo();
info2.ID = 1;
info.Where( ci => ci.ID == info2.ID )
The "where" method is an extension:
public static void Where<T>(this T source, Expression<Func<CaseInfo, bool>> criterias)
{
var remoteexpr = criterias.Body.ToRemoteLinqExpression();
var linqexpr = remoteexpr.ToLinqExpression();
}
Now I can see that the "Right" Operand Expression in 'linqexpr' is of type 'Remote.Linq.DynamicQuery.VariableQueryArgument`1'. Is this a design issue - and if so, how to access the Expression of the Operand?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.