Entity framework 为什么我不能将所有单个存储库方法都放在通用的基本存储库中

Entity framework 为什么我不能将所有单个存储库方法都放在通用的基本存储库中,entity-framework,repository,repository-pattern,Entity Framework,Repository,Repository Pattern,我想从专门的技术角度重新表述这个问题 通常,通用的基本存储库类包含Add、Delete、Update、GetById和GetAll方法 现在我想在这个基类中加入更多的方法,比如EntityExists等等。。。当我需要更具体的东西,需要深入研究IQueryable.GetAll()方法时,我可以将谓词组合/附加到GetAll方法。从技术角度来看,这应该可以节省很多类和接口 但是,当我采用这种方法时,对我的程序有什么负面影响呢?通用基本存储库类应该只实现对所有可能扩展它的存储库都有意义的方法。如果

我想从专门的技术角度重新表述这个问题

通常,通用的基本存储库类包含Add、Delete、Update、GetById和GetAll方法

现在我想在这个基类中加入更多的方法,比如EntityExists等等。。。当我需要更具体的东西,需要深入研究IQueryable.GetAll()方法时,我可以将谓词组合/附加到GetAll方法。从技术角度来看,这应该可以节省很多类和接口


但是,当我采用这种方法时,对我的程序有什么负面影响呢?

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


如果没有更具体的示例(代码),我想我无法提供更多的指导。

基类不是瑞士陆军刀类或实用程序类。坚实的原则也适用于他们

当涉及到存储库时,您可以采取两种方式。第一种是使用规范模式,在该模式中,所有实体都使用相同的存储库类。相反,您要做的是创建小的特定类,这些类可以在查询时组合使用,也可以独立使用。例如:

repository.Query(new FindLockedUsers(new Paging(1, 50)); 
其中
FindLockedUsers
Paging
是两种规范(内部类是
:ed)。实现有点像装饰器模式

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

repository.FindLockedUsers(int pageNumber, int pageSize);

我个人更喜欢后者,因为它使契约更容易遵循(即,我只需要阅读存储库接口/类就可以理解如何使用它)。

如果您遵循OOP原则,我会说您可以随心所欲。通常我有一个接口,它声明了我需要EfDb类实现的所有内容。这样,我的控制器只与我的接口对话,不能直接访问我的EfBd类。请参见下面的示例:

接口

public interface IDataSource
{
    //Person Entities
    IQueryable<Person> Persons{ get; }
    void SavePerson(Person person);        
}
我希望这会有帮助,很抱歉演示了这么长时间,但只要您遵循特定的软件设计原则,如面向对象编程(OOP),一切都应该可以。这一切都取决于对其他类隐藏实现的程度。就像在我的演示中一样,控制器类无法访问我的EfDb类。

IQueryable
是一个泄漏的抽象。在这种情况下,他可以直接使用EF上下文。
    //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);
    }