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

ToQueryDefinition() throws ArgumentNullException on LINQ query without Where clause #1438

Closed
matthewhancock opened this issue Apr 27, 2020 · 6 comments · Fixed by #2580
Closed
Assignees
Labels
bug Something isn't working LINQ

Comments

@matthewhancock
Copy link

Describe the bug
Calling .ToQueryDefinition() throws an ArgumentNullException with message Value cannot be null. (Parameter 'sqlQuery') if a Where clause hasn't been added to the LINQ query.

The string representation of the IOrderedQueryable is the url path to the Container.
image

If I set a dummy lambda (.Where(q => true)) the query works.
image

To Reproduce

new CosmosClient("...connection string here...")
    .GetDatabase("AAA")
    .GetContainer("BBB")
    .GetItemLinqQueryable<Test>()
    .ToQueryDefinition();

Expected behavior
The query will return the Items in the Container.

Actual behavior
An ArgumentNullException is thrown.

Environment summary
SDK Version: 3.6.0 and 3.8.0
OS Version: Windows 10, Visual Studio Professional 2019 16.5.3

Additional context
Was previously reported and closed as Resolved: #719

@V4A001
Copy link

V4A001 commented Feb 11, 2021

I have the same issue I believe. Ethical hackers are concerned about "SELECT * from ".. stuff and LINQ takes care of proper formatting. For that reason (and strong typed) I prefer linq. However, I run in similar issue when trying next:

`public async Task GetCompanyBycompanyNumberAsync(string companyNumber)
{
try
{
IOrderedQueryable queryable = this._container.GetItemLinqQueryable();
queryable.Where(p => p.companyNumber == companyNumber);

            QueryDefinition queryDefinition = queryable.ToQueryDefinition();

            using (FeedIterator feedIterator = this._container.GetItemQueryStreamIterator(
                queryDefinition,
                null,
                new QueryRequestOptions() { PartitionKey = new PartitionKey(Company.PartitionKeyPath) }))
            {
                while (feedIterator.HasMoreResults)
                {
                    using ResponseMessage responseMessage = await feedIterator.ReadNextAsync();
                    if (responseMessage.IsSuccessStatusCode)
                    {
                        var company = StreamExtensions.FromStream<Company>(responseMessage.Content);
                        return company;
                    }
                }
                return null;
            }
            throw new Exception("More than 1 record returned.");
            //var q = this._container.GetItemLinqQueryable<Company>();
            //var iterator = q.Where(p => p.companyNumber == companyNumber).ToFeedIterator();
            //// Can write raw SQL, but the iteration is a little annoying. 
            ////var iterator = this._container.GetItemQueryIterator<Company>($"SELECT * FROM c WHERE c.companyNumber = '{companyNumber}'");
            //while (iterator.HasMoreResults)
            //{
            //    foreach (var item in (await iterator.ReadNextAsync()).Resource)
            //    {
            //        company = item;
            //    }
            //}
            //return company;
        }
        catch (CosmosException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound)
        {
            return null;
        }
    }`

For an ORM I would expect something easier to query on the index key like the PartitionKeyPath which for most developers is not the id to start with. Most likely a user, email or something know and entered by humans.

Help appreciated.

@Matthewsre
Copy link

I just hit this issue as well. Is there at least a way to easily check the IQueryable? I don't want to rely on try/catch for my logic on this.

@j82w
Copy link
Contributor

j82w commented May 3, 2021

@Matthewsre did you hit this running the latest 3.18.0 SDK?

@V4A001
Copy link

V4A001 commented Jun 27, 2021

This isssue is still there with 3.20.0.0

If I add the where clause it works, but without it, it does not:

` Company company = null;
var queryable = this._container.GetItemLinqQueryable();
//.Where(q => true);
queryable.Where(p => p.GLN== gln);

            QueryDefinition queryDefinition = queryable.ToQueryDefinition();`

@sourabh1007
Copy link
Contributor

If you want to Select everything without any condition. Right way to do it is:

_this.container.GetItemLinqQueryable().Select(x => x)

Pasting few links for your reference :
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/select-clause
https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.select?view=net-5.0

@j82w
Copy link
Contributor

j82w commented Jun 29, 2021

If doing the following causes a null ref it still needs to be fixed.

this._container.GetItemLinqQueryable().ToQueryDefinition();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working LINQ
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants