你决定在什么时候创建一个新的Repository?

时间:2011-07-29 05:09:01

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

假设你有这两个类。

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

我去了这个地址:

  

/作者/ 1 /图书

仅使用当前的AuthorRepository是否有意义?

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

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

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

Create动作也会发生同样的事情。我很难决定哪一个更有意义。

[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,如果它有任何区别。

2 个答案:

答案 0 :(得分:3)

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

聚合根可以被认为是“父”,如果没有父母就不能存在“孩子”。

在您的示例中,作者是聚合根,因为如果没有作者图书就不能存在。 (FK证明了这一点)。

因此,您应该拥有一个 LibraryRepository ,它能够与作者和书籍一起使用,具有单个Entity Framework对象集。

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

所以你可能有:

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<Author>(通用存储库上为T。< / p>

然而,看看如何找到一本书很麻烦。如果你发现自己需要自己找一个“孩子”(例如没有先检索父母),那么你也应该考虑创建一个书库。

所以它归结为两件事:

  1. 执行聚合边界
  2. 创建为您的应用程序提供服务的存储库
  3. 考虑用户界面,每个屏幕需要哪些信息,手头有哪些信息来识别该信息(例如URL)。

答案 1 :(得分:0)

我会在单元测试方面看一下。哪种方法可以更简单地测试控制器并验证代码中的测试结果?