2018年3月18日 星期日

範例:ASP.NET Core 2.0 DI & EntityFrameworkCore & Repository Pattern


假設建立了一個 DbContext 叫做 TempDbContext

    public class TempDbContext : DbContext
    {
       
public TempDbContext(DbContextOptions<TempDbContext> options)  : base(options)
        {

        }

       
public DbSet<Product> Products { get; set; }
    }

IRepository<T為一些常用操作(例如CRUD)的 interface
IProductRepository 為操作 Product 的 interface,並包含了IRepository<T>

   
public interface IRepository<T> where T : class
    {
       
IEnumerable<T> GetAll();
       
IEnumerable<T> Find(Func<T, bool> predicate);
       
T GetById(int id);
       
void Create(T entity);
       
void Update(T entity);
       
void Detele(T entity);
       
int Count(Func<T, bool> predicate);
    }

   
public interface IProductRepository : IRepository<Product>
    {
        //
一些操作 Product 的方法
       
Product GetProductByName(string name);
    }

實作 IRepository<T>

    public class Repository<T> : IRepository<T> where T : class
    {
       
// 會利用 ASP.NET Core 2.0 DI 注入實例
        protected readonly TempDbContext _context;
       
public Repository(TempDbContext context)
        {
            _context = context;
        }
       
public void Save() => _context.SaveChanges();

       
public int Count(Func<T, bool> predicate)
        {
           
return _context.Set<T>().Where(predicate).Count();
        }

       
public void Create(T entity)
        {
            _context.Add(entity);
            Save();
        }

       
public void Detele(T entity)
        {
            _context.Remove(entity);
            Save();
        }

       
public IEnumerable<T> Find(Func<T, bool> predicate)
        {
           
return _context.Set<T>().Where(predicate);
        }

       
public IEnumerable<T> GetAll()
        {
           
return _context.Set<T>();
        }

       
public T GetById(int id)
        {
           
return _context.Set<T>().Find(id);
        }

       
public void Update(T entity)
        {
            _context.Entry(entity).State =
EntityState.Modified;
            Save();
        }
    }

實作 IProductRepository,也繼承 Repository<Product>

    public class ProductRepository : Repository<Product>, IProductRepository
    {
       
public ProductRepository(TempDbContext context) : base(context)
        {
        }

       
public Product GetProductByName(string name)
        {
           
return _context
                .Products
                .Where(p => p.Name == name)
                .FirstOrDefault();
        }
    }

ASP.NET Core 2.0 DI 設定(Startup)

        public void ConfigureServices(IServiceCollection services)
        {
           
// Repository 建構子需要 DbContext
            services.AddDbContext<TempDbContext>(options => options.UseInMemoryDatabase("TempContext"));
            services.AddTransient<
IProductRepository, ProductRepository>();
            services.AddMvc();
        }

Controller 中使用 Repository

    [Route("api/[controller]")]
   
public class ProductController : Controller
    {
       
private readonly IProductRepository _productRepository;

       
public ProductController(IProductRepository productRepository)
        {
            _productRepository = productRepository;
        }
    }

==========
Debug:
在執行時發生了這個錯誤

Additional information: No database provider has been configured for this DbContext. A provider can be configured by overriding the DbContext.OnConfiguring method or by using AddDbContext on the application service provider. If AddDbContext is used, then also ensure that your DbContext type accepts a DbContextOptions object in its constructor and passes it to the base constructor for DbContext.
確定在ConfigureServices有設定DbContext的注入,後來發現是TempDbContext的建構子忘了呼叫base(options)

沒有留言: