3

我一直在寻找一些博客帖子,试图创建一个适合以下要求的解决方案,但我似乎无法将它们拼凑在一起。希望完全有人可以帮忙。MVC仓库与工作单元,自动映射器和通用仓库

我一直在使用使用Automapper接口库模式......这里有一个下调例如:

public class BookingRepository : IBookingRepository 
{ 
    Entities context = new Entities(); 

    public IEnumerable<BookingDto> GetBookings 
    { 
     get { return Mapper.Map<IQueryable<Booking>, IEnumerable<BookingDto>>(context.Bookings); } 
    } 

    public BookingDto GetBookingWithProduct(Guid bookingId) 
    { 
     return Mapper.Map<BookingDto>(context.Bookings.Include(c => c.Products).SingleOrDefault(c => c.BookingId == bookingId)); 
    } 

    public void Update(BookingDto bookingDto) 
    { 
     var booking = Mapper.Map<Booking>(bookingDto); 
     context.Entry(booking).State = EntityState.Modified; 
    } 

    public void Save() 
    { 
     context.SaveChanges(); 
    } 

    public void Dispose() 
    { 
     context.Dispose(); 
    } 
} 

public interface IBookingRepository : IDisposable 
{ 
    IEnumerable<BookingDto> GetBookings { get; } 
    BookingDto GetBooking(Guid bookingId); 
    void Update(BookingDto bookingDto); 
    void Save(); 
} 

随着不同的实体一个单独的存储库,例如

public class ProductRepository : IProductRepository 
{ 
    Entities context = new Entities(); 

    public IEnumerable<ProductDto> GetProducts 
    { 
     get { return Mapper.Map<IQueryable<Product>, IEnumerable<ProductDto>>(context.Products); } 
    } 

    public ProductDto GetProductWithDesign(int productId) 
    { 
     return Mapper.Map<ProductDto>(context.Products.Include(c => c.Designs).SingleOrDefault(c => c.ProductId == productId)); 
    } 

    public void Update(ProductDto productDto) 
    { 
     var product = Mapper.Map<Product>(productDto); 
     context.Entry(product).State = EntityState.Modified; 
    } 

    public void Save() 
    { 
     context.SaveChanges(); 
    } 

    public void Dispose() 
    { 
     context.Dispose(); 
    } 
} 

public interface IProductRepository : IDisposable 
{ 
    IEnumerable<ProductDto> GetProducts { get; } 
    ProductDto GetProduct(int productId);  
    void Update(ProductDto productDto); 
    void Save(); 
} 

然后在我的控制器中,我使用的库如下:

public class HomeController : Controller 
{ 
    private readonly IBookingRepository bookingRepository; 
    private readonly IProductRepository productRepository; 

    public HomeController() : this(new BookingRepository(), new ProductRepository()) { } 
    public HomeController(IBookingRepository bookingRepository, IProductRepository productRepository) 
    { 
     this.bookingRepository = bookingRepository; 
     this.productRepository = productRepository; 
    } 

    protected override void Dispose(bool disposing) 
    { 
     base.Dispose(disposing); 

     if (disposing && this.bookingRepository != null) 
      this.bookingRepository.Dispose(); 

     if (disposing && this.productRepository != null) 
      this.productRepository.Dispose(); 

    } 
} 

因此,现在我希望创建一个工作单元来抽象这些存储库并共享上下文,并为重复操作(保存和更新)创建一个通用存储库,同时记住我正在传递Dtos和映射到实体对象。我很难理解如何将它们结合在一起。

此外,我已经看到了这个帖子

Repository pattern with generics and DI

其中指出:“你不应该有除了你的通用仓库等库接口”和自定义查询“应该拥有自己的(通用)抽象:”这是增加了我的劳累过度的大脑的另一个复杂因素,因为我的存储库将具有使用包含语句返回复杂链接对象的自定义查询,因为禁用了“延迟加载”。

所以我准备好被击落,并告诉我这是错误的方式,但会感谢任何方向。

在此先感谢。

回答

5

不要使用普通的仓库。他们都是抽象的抽象。问问自己,通过使用抽象并不能真正抽象出什么东西,你会得到什么好处?您可以直接在这些情况下使用您的OR/M。

我的意思是任何公开IQueryable<T>都会强制用户了解底层OR/M所具有的弱点。例子:orm如何处理延迟加载?我如何急切地加载相关实体?如何创建IN子句?

如果您真的想要使用存储库模式,请将其与规范模式一起使用(您可以继续使用通用存储库)或创建特定于每个根聚合的存储库。

我的博客上讲述它:http://blog.gauffin.org/2013/01/repository-pattern-done-right/

+0

我觉得你的文章很有趣,但看起来你实际上正在展示如何创建一个通用库。 – reddy 2014-06-04 06:52:58

+0

@Joey:重要的区别是我不直接使用它,而是继承它。 – jgauffin 2014-06-04 07:47:47

+0

这很有道理,谢谢 – reddy 2014-06-04 07:50:33

0

我通常在这种情况下,做的是创建一个抽象基类存储库这样的:

public abstract class BaseRepository<T> : IRepository<T> 
{ 
    Entities context = new Entities(); 

    public virtual T GetAll() 
    { 
     return context.Set<T>(); 
    } 
    // Add base implementation for normal CRUD here 
} 

如果你不需要特殊的查询,那么你就需要建立特殊的接口和类(但你当然可以提高可读性)。所以,你会使用,例如:

var bookingsRepo = new BaseRepository<BookingsDto>(); 
var allBookings = bookingsRepo.GetAll(); 

如果你需要一些特殊的查询,您创建一个扩展底座接口的接口:

public interface IProductRepository : IRepository<Product> 
{ 
    Product GetSpecialOffer(); 
} 

然后创建类:

public class ProductRepository : BaseRepository<Product>, IProductRepository 
{ 
    public Product GetSpecialOffer() 
    { 
     // your logic here 
    } 
} 

这样,您只需指定最少数量的特殊情况,同时依赖基本抽象实现来处理所有事情。

我加virtual到基本方法,因为我总是喜欢给派生类重写的东西的能力...

+0

嗨Tallmaris ...感谢您的答复......你会因此如何解释这个事实,该库正在返回的DTO,而不是实体对象。我需要Generic存储库以某种方式使用Automapper来返回Dtos。 – ledragon 2013-05-01 12:32:24

+0

我相信是这样的,你可以使用AutoMapper来在你的对象之间前后映射。 – Tallmaris 2013-05-01 13:15:43