3

我一直在看一些博客文章,试图为以下要求创建一个合适的解决方案,但我似乎无法将它们拼凑在一起。完全希望有人可以提供帮助。

我一直在使用带有 Automapper 接口的 Repository 模式......这是一个精简的例子:

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 并映射到实体对象。我很难理解如何将它们编织在一起。

另外,我看过这个帖子

具有泛型和 DI 的存储库模式

其中指出“除了通用存储库之外,您不应该有其他存储库接口”,并且自定义查询“值得拥有自己的(通用)抽象:”这给我过度劳累的大脑增加了另一个复杂性,因为我的存储库将具有返回复杂链接对象的自定义查询使用包含语句作为延迟加载被禁用。

所以我准备好被击落,并告诉我我会以错误的方式解决这个问题,但我会感谢任何给出的方向。

提前致谢。

4

2 回答 2

5

不要使用通用存储库。它们都是泄漏的抽象。问问自己,通过使用并没有真正抽象出某些东西的抽象对你有什么好处?在这些情况下,您可以直接使用您的 OR/M。

我的意思是任何暴露的东西都会IQueryable<T>迫使用户了解底层 OR/M 的弱点。示例: orm 如何处理延迟加载?如何急切地加载相关实体?如何创建IN子句?

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

我在博客上写过:http: //blog.gauffin.org/2013/01/repository-pattern-done-right/

于 2013-05-02T11:31:44.913 回答
0

在这种情况下,我通常做的是创建一个 Base 抽象 Repository 类,如下所示:

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
    }
}

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

我添加virtual到基本方法是因为我总是喜欢让派生类能够覆盖东西......

于 2013-05-01T11:42:10.920 回答