I'm using Polly to wrap all of my database commands in case of connection errors but I'm getting the above error when trying to write a custom method to run the Polly code. I'm using Entity Framework 6 and I thought I did everything right but obviously I missed something. This is pseudo code but hopefully you get the idea.
DbSet< TableName > does not contain a definition for 'Where' and the best extension method overload 'Queryable.Where< T >(IQueryable< T >, Expression<Func<T, bool>>)' requires a receiver of type IQueryable< T >
public static async Task<List<T>> HandleNetworkTask<T>(Expression<Func<T, bool>> expression, T table) where T : class
{
try
{
using var context = new dbconfig();
int maxRetries = 5;
var retryPolicyAsync = Policy<T>.Handle<Exception>().WaitAndRetryAsync(maxRetries, retryAttempt => TimeSpan.FromSeconds(1), (exception, timeSpan, retryCount, context) =>
{
Thread.Sleep(6000);
});
var fallbackPolicyAsync = Policy<T>.Handle<Exception>().FallbackAsync(fallbackValue: null, onFallbackAsync: async (exc, con) => await ThrowExceptionInfo(exc.Exception));
var retryPolicy = Policy<T>.Handle<Exception>().WaitAndRetry(maxRetries, retryAttempt => TimeSpan.FromSeconds(1), (exception, timeSpan, retryCount, context) =>
{
Thread.Sleep(6000);
});
var fallbackPolicy = Policy<T>.Handle<Exception>().Fallback(fallbackValue: null, onFallback: (exc, con) => ThrowExceptionInfo(exc.Exception).GetAwaiter().GetResult());
switch (table)
{
case TableName:
return await fallbackPolicyAsync.WrapAsync(retryPolicyAsync).ExecuteAsync(async () =>
{
return await context.TableName.Where<T>(expression).ToListAsync();
});
break;
default:
break;
}
}
catch (Exception ex)
{
ThrowExceptionInfo(ex);
}
}
This is how I'm calling the method in my code:
var list = await HandleNetworkTask(x => x.Name == name && x.Date == date, new TableName(), true);
When it comes to generics, I believe this type of code is illegal.
switch (table)
{
case TableName:
return await fallbackPolicyAsync.WrapAsync(retryPolicyAsync).ExecuteAsync(async () =>
{
return await context.TableName.Where<T>(expression).ToListAsync();
});
You can't run an Expression<Func<T, bool>>
against DbSet<TableName>
even though you've effectively asserted T = TableName in this scenario.
What you can do is remove the whole table check (other than asserting it is a valid entity table) and executing:
return await context.Set<T>.Where(expression).ToListAsync();
I'd consider removing the "table" parameter and just call your method with the Type in the generic call:
var list = await HandleNetworkTask<TableName>(x => x.Name == name && x.Date == date, true);
From there you can inspect <T>
within the method to assert that the only table passed in is a supported DbSet in your Context, throwing something meaningful if it's called for a table that isn't supported.