将存储库模式应用于ReportViewModels

时间:2015-03-02 14:51:27

标签: c# entity-framework design-patterns repository-pattern

public interface IRepository<TEntity> 
{
    TEntity FindById(Guid id);
    void Add(TEntity entity);
    void Remove(TEntity entity);
}

这是一个简单的通用存储库。如果我有一个Product实体,则此存储库可以插入,更新和删除(使用实体框架)。

但我创建了基于报告的类型。

例如:

  • 按销售人员分组的产品。
  • 每个托运人发送的订单数量。

    public class OrdersWithShipper {
         public string ShipperName{get;set;}
         public string NumberOfOrder{get;set;}
    }
    

等等。

所以我应该为许多相关的表创建复杂的查询。但查询结果对象未使用存储库TEntity实体类型表示。

我有很多这样的报告类型。我怎么解决这个问题?

2 个答案:

答案 0 :(得分:2)

这个问题的直接问题是:

  

所以我应该为许多相关的表创建复杂的查询。但   查询结果对象未使用存储库TEntity实体表示   类型。

我会说你不应该在这里使用存储库模式,因为它打破了它。例如,存储库应该处理返回和管理它所针对的域对象,以支持域行为,而不是随机查询对象以支持报告行为。

如果不坚持使用相同的类型,您几乎肯定不知道在哪里绘制线条,例如查询对象与哪个存储库等等...所以你应该保持简单。

例如,将不同的模式应用于报告(或查询)。也许为您的视图模型创建类(View Model Builders?),它们直接依赖于IDbSet<T>来查询逻辑。

或者,进一步抽象并具有查询处理程序/查询提供程序模式(这将是我的选择)。

看看这里的答案:

Well designed query commands and/or specifications

我使用了类似的模式并取得了巨大的成功。

答案 1 :(得分:0)

我这样做的技巧是将Repository包装在可以接受ViewModel的Service类中。换句话说,我的控制器正在使用我制作的服务类而不是直接使用存储库。 另外,我使用AutoMapper库来映射

以下示例:

public class OrderWithShipperProductService()
{
    public ProductRepository { get; set; }

    public OrderWithShipperProductService(ProductRepository repo)
    {
        this.ProductRepository = repo;
    }

    public void AddOrderWithShipperProduct(OrderWithShipperProduct model)
    {
        var entity = Mapper.Map<TEntity>(model);
        ProductRepository.Add(entity);
    }
}

您可能需要学习Automapper here。 但是如果需要,您也可以在构造函数中自己映射它。 或者您也可以创建自己的映射函数。