Adapter pattern for IDbSet properties of a DbConte

2019-05-22 02:43发布

问题:

Is there a way to use the method described in this answer No FindAsync() method on IDbSet for DbSet properties of a DbContext?

Edit:

The answer linked contains a description how to build a interface inheriting from IDbSet and adding support for the SearchAsync method of the DbSet class. I understand everything which Keith Payne has written, but I don’t know how I can use it in DbContext.

For example I’ve a DbContext which looks something like this:

public class MyContext : DbContext
{ 
    public DbSet<Customer> Customers { get; set; }
}

How can I use MyDbSet (class described in the answer.) or a similar class, instead of DbSet?

public class MyContext : DbContext
{ 
    public MyDbSet<Customer> Customers { get; set; }
}

The problem is now, that Entity Framework seem to generate only tables for properties of type IDbSet or DbSet.

回答1:

You have regular DbSet on your context and create an adapter adding the requested interface.

public interface IAsyncDbSet<T> : IDbSet<T>
    where T : class
{
    Task<T> FindAsync(params Object[] keyValues);
}

public sealed class DbSetAdapter<T> : IAsyncDbSet<T>, IDbSet<T>
    where T : class
{
    private readonly DbSet<T> _innerDbSet;

    public DbSetAdapter(DbSet<T> innerDbSet)
    {
        _innerDbSet = innerDbSet;
    }

   public Task<T> FindAsync(params object[] keyValues)
   {
          return _innerDbSet.FindAsync(keyValues);
   }

   //Here implement each method so they call _innerDbSet like I did for FindAsync
}

Now you can create a DbSetAdapater when you need it and get an IAsyncDbSet. You could duplicate your properties as EF seems to ignore them or add an ToAsyncDbSet() extension method to IDbSet<T>

public class MyContext : DbContext
{ 
    public DbSet<Customer> Customers { get; set; }
    public IAsyncDbSet<Customer> CustomersAsync { get { return new DbSetAdapter<Customer>(Customers); } }
}