简体   繁体   中英

DbSet<TableName> does not contain a definition for 'Where' and the best extension method overload

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM