Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ArgumentOutOfRangeException when combineing Model projection with Where-In in linq query #81

Closed
mmsommer opened this issue Nov 26, 2015 · 8 comments

Comments

@mmsommer
Copy link

A where in, or Array.Contains(..) linq query results in an ArgumentOutOfRangeException when a projection (as in Select(x => x.projection)) is used before the where clause.

System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
Parameter name: Unexpected Sql Scalar expression kind InExpression

I expected it to not fail and translate the expression into a where in query to Azure Documents.

Test code:

using System;
using System.Linq;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using Microsoft.Azure.Documents.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;

[TestClass]
public class DocumentTests
{
    private DocumentClient _client;
    private Database _database;
    private DocumentCollection _documentCollection;

    [TestInitialize]
    public void Setup()
    {
        _client = new DocumentClient(new Uri("uri"),"secret");
        _database = _client.CreateDatabaseQuery().Where(db => db.Id == "DocumentTesting").AsEnumerable().FirstOrDefault();

        if (_database == null)
        {
            _database = _client.CreateDatabaseAsync(
                new Database
                {
                    Id = "DocumentTesting"
                }).Result;
        }

        _documentCollection = _client.CreateDocumentCollectionQuery("dbs/" + _database.Id)
            .Where(c => c.Id == "TestCollection").AsEnumerable()
            .FirstOrDefault();

        if (_documentCollection == null)
        {
            _documentCollection = _client.CreateDocumentCollectionAsync(
                "dbs/" + _database.Id,
                new DocumentCollection
                {
                    Id = "TestCollection"
                }).Result;
        }

        var document = _client.CreateDocumentQuery<TestResource>("dbs/" + _database.Id + "/colls/" + _documentCollection.Id)
            .Where(d => d.Name == "foo").AsEnumerable()
            .FirstOrDefault();

        if (document == null)
        {
            document = new TestResource { Name = "foo", Model = new TestModel { Name = "bar" } };

            _client.CreateDocumentAsync("dbs/" + _database.Id + "/colls/" + _documentCollection.Id, document).Wait();
        }
    }

    [TestMethod]
    public void WhereInQuery_WithoutProjection_WithStaticList()
    {
        var result = _client.CreateDocumentQuery<TestResource>(_documentCollection.DocumentsLink)
                .Where(res => new[] { "foo" }.Contains(res.Name))
                .AsEnumerable().ToArray();

        Assert.AreEqual("foo", result.First().Name);
    }

    [TestMethod]
    public void WhereInQuery_WithoutProjection_WithDynamicList()
    {
        var names = new[] { "foo" };
        var result =
            _client.CreateDocumentQuery<TestResource>(_documentCollection.DocumentsLink)
                .Where(res => names.Contains(res.Name))
                .AsEnumerable().ToArray();

        Assert.AreEqual("foo", result.First().Name);
    }

    [TestMethod]
    public void WhereInQuery_WithProjection_WithStaticList()
    {
        var result =
            _client.CreateDocumentQuery<TestResource>(_documentCollection.DocumentsLink)
                .Select(res => res.Model)
                .Where(res => new[] { "bar" }.Contains(res.Name))
                .AsEnumerable().ToArray();

        Assert.AreEqual("bar", result.First().Name);
    }

    [TestMethod]
    // !!! THIS ONE FAILS !!!
    public void WhereInQuery_WithProjection_WithDynamicList()
    {
        var names = new[] { "bar" };
        var result =
            _client.CreateDocumentQuery<TestResource>(_documentCollection.DocumentsLink)
                .Select(res => res.Model)
                .Where(res => names.Contains(res.Name))
                .AsEnumerable().ToArray();

        Assert.AreEqual("bar", result.First().Name);
    }

    private class TestResource : Resource
    {
        public string Name { get; set; }
        public TestModel Model { get; set; }
    }

    private class TestModel
    {
        public string Name { get; set; }
    }
}
@mmsommer mmsommer changed the title Array.Contains linq provider implementation is leaky ArgumentOutOfRangeException when combineing Model project with Where-In in linq query Nov 26, 2015
@mmsommer mmsommer changed the title ArgumentOutOfRangeException when combineing Model project with Where-In in linq query ArgumentOutOfRangeException when combineing Model projection with Where-In in linq query Nov 26, 2015
@ghost
Copy link

ghost commented Nov 30, 2015

Confirmed as a problem. Fix has been submitted for review. Will get a new deployment asap.

@ghost
Copy link

ghost commented Dec 8, 2015

Should be deployed within the next few days.

@wis3guy
Copy link

wis3guy commented Dec 8, 2015

That is great news!

@ghost
Copy link

ghost commented Dec 14, 2015

fixed in 1.5.2

@ghost ghost closed this as completed Dec 14, 2015
@wis3guy
Copy link

wis3guy commented Dec 16, 2015

@ryancrawcour We have updated our nuget package to 1.5.2 and reran our tests. Our conclusion is that the provided unit test still fails erroneously.

At this point i'm not sure what is going on. Did the fix not make it into the latest nuget package? Was the bug not understood and was something else fixed?

@ghost ghost reopened this Dec 16, 2015
@ghost
Copy link

ghost commented Dec 16, 2015

Here's the unit test we built (derived from the code above) - https://gist.github.com/ryancrawcour/a833cd0f0543fcc9a8a4

This failed first which led us to finding the problem.
It now passes in 1.5.2 after fix was applied.

Are you able to get the sql statement from the query? Or does it fail before it even gets here?

@mmsommer
Copy link
Author

I did try to catch a sql statement with Fiddler, but none came through. Apparently it fails before it gets there.

This is the stacktrace I got returned:

System.AggregateException: One or more errors occurred. ---> System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
Parameter name: Unexpected Sql Scalar expression kind InExpression
   at Microsoft.Azure.Documents.Linq.SqlExpressionManipulation.Substitute(SqlScalarExpression replacement, SqlIdentifier toReplace, SqlScalarExpression into)
   at Microsoft.Azure.Documents.Linq.QueryUnderConstruction.Substitute(SqlSelectSpec spec, SqlIdentifier inputParam, SqlWhereClause whereClause)
   at Microsoft.Azure.Documents.Linq.QueryUnderConstruction.Flatten()
   at Microsoft.Azure.Documents.Linq.ExpressionToSql.TranslateQuery(Expression inputExpression)
   at Microsoft.Azure.Documents.Linq.SQLTranslator.TranslateQuery(Expression inputExpression)
   at Microsoft.Azure.Documents.Linq.DocumentQueryEvaluator.HandleMethodCallExpression(MethodCallExpression expression)
   at Microsoft.Azure.Documents.Linq.DocumentQueryEvaluator.Evaluate(Expression expression)
   at Microsoft.Azure.Documents.Linq.DocumentQueryExecutionContext.<ExecuteAllAsync>d__7.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Azure.Documents.Linq.DocumentQuery`1.<GetEnumeratorTAsync>d__10.MoveNext()
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at System.Threading.Tasks.Task`1.get_Result()
   at Microsoft.Azure.Documents.Linq.DocumentQuery`1.GetEnumerator()
   at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
   at DocumentTests.WhereInQuery_WithProjection_WithDynamicList() in C:\Workplace\Gfms\Tns.Nipo.Gfms.Core.Tests\Infrastructure\DocumentTests.cs:line 96
---> (Inner Exception #0) System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
Parameter name: Unexpected Sql Scalar expression kind InExpression
   at Microsoft.Azure.Documents.Linq.SqlExpressionManipulation.Substitute(SqlScalarExpression replacement, SqlIdentifier toReplace, SqlScalarExpression into)
   at Microsoft.Azure.Documents.Linq.QueryUnderConstruction.Substitute(SqlSelectSpec spec, SqlIdentifier inputParam, SqlWhereClause whereClause)
   at Microsoft.Azure.Documents.Linq.QueryUnderConstruction.Flatten()
   at Microsoft.Azure.Documents.Linq.ExpressionToSql.TranslateQuery(Expression inputExpression)
   at Microsoft.Azure.Documents.Linq.SQLTranslator.TranslateQuery(Expression inputExpression)
   at Microsoft.Azure.Documents.Linq.DocumentQueryEvaluator.HandleMethodCallExpression(MethodCallExpression expression)
   at Microsoft.Azure.Documents.Linq.DocumentQueryEvaluator.Evaluate(Expression expression)
   at Microsoft.Azure.Documents.Linq.DocumentQueryExecutionContext.<ExecuteAllAsync>d__7.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Azure.Documents.Linq.DocumentQuery`1.<GetEnumeratorTAsync>d__10.MoveNext()<---

@ghost
Copy link

ghost commented Jan 20, 2016

per email conversation with @mmsommer this is now working. closing the issue as resolved.

@ghost ghost closed this as completed Jan 20, 2016
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants