为什么我不能将所有单独的存储库方法放在通用基础存储库中

时间:2013-02-23 21:15:17

标签: entity-framework repository repository-pattern

我想在独家技术角度重述这个问题。

通常,通用基础存储库类包含Add,Delete,Update,GetById和GetAll方法。

现在我很想把更多的方法放在这个基类中,比如EntityExists等......当我需要更多特定的东西时,我必须深入了解IQueryable.GetAll()方法我可以编写/附加谓词GetAll方法。这应该可以节省我从技术方面看到的许多类和接口。

但是当我遵循这种方法时,对我的计划有什么负面影响?

3 个答案:

答案 0 :(得分:0)

通用基本存储库类应该只实现对可能扩展它的所有存储库有意义的方法。如果你有这些方法的例子不会违反任何SOLID原则,我会说可以随意添加到这个基类。

如果没有更具体的例子(代码),我认为我不能提供更多指导。

答案 1 :(得分:0)

基础类不是瑞士军刀或实用类。 SOLID原则也适用于它们。

说到存储库,你可以采取两种方式。第一个是使用规范模式,您对所有实体使用相同的存储库类。你要做的是创建小的特定类,在查询时可以组合或使用它们。例如:

repository.Query(new FindLockedUsers(new Paging(1, 50)); 

其中FindLockedUsersPaging是两个规范(内部类是AND:ed)。实现是一种装饰模式。

另一种方法是为每个实体(根聚合)使用特定的存储库。这些get方法按实体定制,如:

repository.FindLockedUsers(int pageNumber, int pageSize);

我个人更喜欢后者,因为它使合同更容易遵循(即我只需要阅读存储库接口/类来了解如何使用它)。

答案 2 :(得分:0)

如果您遵循OOP原则,我会说您可以按照自己的意愿行事。通常我有一个接口,声明我需要实现的所有EfDb类。这样,我的控制器只与我的界面对话,并且无法直接访问我的EfBd类。请参阅以下示例:

<强>接口

public interface IDataSource
{
    //Person Entities
    IQueryable<Person> Persons{ get; }
    void SavePerson(Person person);        
}

EfDb类

    //Person
    public DbSet<Person> Persons { get; set; }
    IQueryable<Person> IDataSource.Persons
    {
        get { return Persons; }
    }


    public void SavePerson(Person person)
    {
        using (var context = new EFootballDb())
        {
            if (person.PersonId == 0)
            {
                context.Persons.Add(player);
            }
            else if (person.PersonId > 0)
            {
                 var currentPerson = context.Persons
                    .Single(p => p.PersonId == person.PersonId);

                context.Entry(currentPerson ).CurrentValues.SetValues(person);                    
            }
            context.SaveChanges();
        }
    }

然后在您的控制器中,您只需按照以下方式调用您的界面,并执行以下创建操作。

 public class PersonController : Controller
 {

    private readonly IDataSource _dataSource;

    public PersonController(IDataSource dataSource)
    {
        _dataSource = dataSource;
    }

    [HttpGet]
    public ActionResult Create()
    {
        return View();
    }

    [HttpPost]
    public ActionResult Create(Person model)
    {
       try
        {
            if (ModelState.IsValid)
            {                
                _dataSource.SavePerson(model);
                return RedirectToAction("Index", "Home");
            }
        }
        catch (Exception)
        {
            ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
        }
        return View(model);
    }

我希望这很有帮助,对于长时间的演示感到抱歉,但只要您遵循某种软件设计原则,如面向对象编程(OOP),一切都应该没问题。这一切都归结为你如何将实现隐藏在其他类中。就像在我的演示中一样,控制器类无法访问我的EfDb类。