"Fluent methods may not be invoked on a Query created via CloudTable.CreateQuery<T>()" exception
Asked Answered
P

2

15

What does the following exception means?

System.NotSupportedException was unhandled Message: An unhandled exception of type 'System.NotSupportedException' occurred in mscorlib.dll Additional information: Fluent methods may not be invoked on a Query created via CloudTable.CreateQuery()

It does not show the code throwing the exception so I don't know how to start debugging it.

Result StackTrace: at System.Web.Http.ApiController.d__1.MoveNext() --- End of inner exception stack trace --- at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions) at System.Threading.Tasks.Task1.GetResultCore(Boolean waitCompletionNotification) at System.Threading.Tasks.Task1.get_Result() at TestFramework.ExecuteRequest(HttpRequestMessage request) in d:\ at TestFramework.Post(String uri, Object tniObject) in d:\ at TestFramework.PostCall(String uri, Object o) in d:\ at TestFramework.MyMethod(String one, String two, MyStruct three) in d:\ ... (Removed for privacy)

I believe the problem is in the following instruction.

string queryString = TableQuery.CombineFilters(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, myId),
                                               TableOperators.And,
                                               TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.Equal, number));
var theQuery = MyTable.CreateQuery<MyEntity>().Where(queryString);

can I use theQuery then to perform a segmented async query?

var returnList = new List<T>();
TableQuerySegment<T> querySegment = null;

querySegment = await theQuery.AsTableQuery().ExecuteSegmentedAsync(null);

// The query could potentially return more than one object
returnList.AddRange(querySegment);

Well, changing the CreateQuery method call to the following code made the exception to go away.

 var query = new TableQuery<TenantTNEntity>().Where(queryString);

The exception I get now says:

Result Message: Test method MyMethod threw exception:

System.AggregateException: One or more errors occurred. ---> System.InvalidOperationException: Unknown Table. The TableQuery does not have an associated CloudTable Reference. Please execute the query via the CloudTable ExecuteQuery APIs.

Pantisocracy answered 31/1, 2014 at 16:11 Comment(4)
What's the stack trace?Coursing
@Coursing stack trace providedPantisocracy
What version of Azure client library are you using?Deform
@Deform Microsoft.WindowsAzure.StorageClient version 1.7.0.0Pantisocracy
L
31

I don't know if this is specifically your problem, but it certainly was mine, and it took me a while to figure out. For reasons that I'm not entirely clear on, the Azure team has provided two different and incompatible ways to execute queries - and although they're incompatible at runtime, the Azure team has helpfully (not!) made sure that they have compatible signatures at compile time.

See the difference between the "Fluent" and "IQueryable" modes described here:

http://blogs.msdn.com/b/windowsazurestorage/archive/2013/09/07/announcing-storage-client-library-2-1-rtm.aspx

In other words, both of these will compile and run and do more or less the same thing:

var fluentQuery = new TableQuery<T>().Where(filter);
var fluentResult = Table.ExecuteQuery(fluentQuery);

var iQueryableQuery= from ent in Table.CreateQuery<T>() 
                     where ent.PartitionKey == "some value" 
                     select ent;
var iQueryableResult = iQueryableQuery.AsTableQuery().Execute();

But while this one will compile just fine, it will blow up at runtime with the System.NotSupportedException that you (and I) ran into.

var fluentQuery2 = Table.CreateQuery<T>().Where(filter);
var fluentResult2 = fluentQuery2.Execute();

I'm sure that the folks at MS had some good reason for this particular violation of the Principle of Least Astonishment - they're not idiots - but it certainly remains the case that this behavior is, shall we say, unusual.

Lissettelissi answered 4/8, 2014 at 5:14 Comment(9)
For those of us familiar with entityframework, you cannot just write the IQueryable statement and call one of the enumeration methods (e.g. ToList) for this to work. You have to call AsTableServiceQuery().Execute() on the IQueryable before you enumerate.Singlehandedly
@Singlehandedly Where do you get AsTableServiceQuery() extension from? I tried utilizing this but couldn't find it.Fossette
@Fossette Microsoft.WindowsAzure.StorageClient (which is both the name of namespace and the dll)Singlehandedly
what version? 6.1.0 of WindowsAzure.Storage is what I'm using nuget.org/packages/WindowsAzure.Storage/6.1.0 StorageClient doesn't exist (nor Storage.Client)Fossette
@Fossette Sorry for the late response, it's part of the Azure SDK azure.microsoft.com/en-us/downloads I don't think it's available from nuget (which is strange)Singlehandedly
hm. strange. no worries, we're doing it another way. also, it looks obsolete msdn.microsoft.com/en-us/library/azure/jj717613.aspxFossette
Exactly! I was struggling to find out the reason. In case you want to use it async use ExecuteQuerySegmentedAsync. Thanks @Ken SmithPlanetary
Thanks for the link. My problem was trying to call take directly on the queryable. Adding a .Select(c => c) before the take allowed the query to complete.Turnip
Almost gave up on this until I saw this post. Thx!Equiangular
A
9

Adding ".AsQueryable()" before ".Take(x)" will make it run

Amentia answered 2/9, 2017 at 8:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.