【问题标题】:At what point do you decide you should create a new Repository?在什么时候你决定你应该创建一个新的存储库?
【发布时间】:2011-07-29 05:09:00
【问题描述】:

假设你有这两个类。

public class Author
{
public int ID {get; set;}
public string Name{get; set;}
public virtual ICollection<Book> Books { get; set;}
}

public class Book
{
public int ID {get; set;}
public string Name{get; set;}
public int AuthorId {get; set;}
public virtual Author Author{ get; set;}
}

如果我有一个 BooksController,它的所有操作都会收到一个 AuthorId

我去这个地址:

/Authors/1/书籍

只使用当前的 AuthorRepository 有意义吗?

public ActionResult Index(int AuthorId)
    {
    return View(_AuthorRepository.GetById(AuthorId).Books)
    }

或者为了保持存储库中的数据访问,我应该创建一个 BookRepository?

public ActionResult Index(int AuthorId)
    {
    return View(_BookRepository.GetByAuthorId(AuthorId))
    }

创建操作也会发生同样的事情。我很难决定哪个更有意义。

[HttpPost]
public ActionResult Create(int AuthorId, BookViewModel book)
{
if(ModelState.IsValid)
{
Book b= new Book();
b= AutomapperMagicMethodThatGivesMeABookFromA(book); //
_AuthorRepository.FindById(AuthorId).Books.Add(b);
_AuthorRepository.SaveChanges();
return RedirectToAction("Index");
}
return View(book)
}

或者这种方法。

[HttpPost]
public ActionResult Create(int AuthorId, BookViewModel book)
{
if(ModelState.IsValid)
{
Book b= new Book();
b= AutomapperMagicMethodThatGivesMeABookFromA(book); //
b.AuthorId = AuthorId;
_BookRepository.Add(b);
_BookRepository.SaveChanges();
return RedirectToAction("Index");
}
return View(book)
}

对于处理此类情况的一些建议,我将不胜感激。 随意批评我的代码。

请帮忙提前谢谢。

ps。我正在使用 EF,如果有什么不同的话。

【问题讨论】:

    标签: asp.net-mvc entity-framework repository repository-pattern


    【解决方案1】:

    一般的经验法则是每个聚合根创建一个存储库

    聚合根可以被认为是“父”,而“子”不能没有父而存在。

    在您的示例中,Author 是聚合根,因为没有 Author 就无法存在 Book。 (FK 证明了这一点)。

    因此,您应该只拥有一个 LibraryRepository,它能够与作者和书籍一起使用,并具有单个实体框架对象集。

    我们实际上是通过将 ObjectSet 键入到 Repository 上的泛型类型来在我们的 Repository 中强制执行这些聚合边界。

    所以你可能有:

    public class LibraryRepository : IRepository<Author>, GenericRepository<Author>
    {
       public Author FindById(int id)
       {
          return _context.SingleOrDefault(x => x.AuthorId == id);
       }
    
       public Book FindById(int bookId)
       {
          return _context
             .Where(x => x.Books.Any(y => y.BookId == bookId))
             .Select(x => x.Books.SingleOrDefault(x => x.BookId == bookId))
             .SingleOrDefault();
       }
    }
    

    在上面的示例中,_context 是通用存储库中的protected 属性,其类型为ObjectSet&lt;Author&gt;(即通用存储库上的T)。

    但是,看看找一本书是多么的麻烦。如果您发现自己需要自己找到一个“孩子”(例如,不先检索父母),那么您也应该考虑创建一个图书存储库。

    所以归结为两件事:

    1. 强制执行聚合边界
    2. 创建服务于您的应用程序的存储库

    想想用户界面,每个屏幕需要什么信息,手头有什么信息来识别那条信息(例如 URL)。

    【讨论】:

    • 好吧,如果用户愿意,BooksController 还必须能够编辑/更新一本书。通过转到“/Author/1/Books/Edit/5”之类的网址,因此肯定需要按 Id 查找一本书....这个理由足以创建 BookRepository 吗?
    【解决方案2】:

    我会在单元测试方面来看看它。哪种方法可以更轻松地测试控制器和验证代码中的测试结果?

    【讨论】:

      猜你喜欢
      • 2010-10-09
      • 1970-01-01
      • 2011-01-15
      • 1970-01-01
      • 1970-01-01
      • 2012-11-13
      • 1970-01-01
      • 2018-12-28
      • 1970-01-01
      相关资源
      最近更新 更多