假设你有这两个类。
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))
}
创建操作也是如此。我很难决定哪一个更有意义。
[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)
}
我希望你能给我一些处理这种情况的建议。请随意批评我的代码。
请帮忙提前谢谢。
p。如果有区别的话,我用EF
一般的经验法则是为每个聚合根创建一个存储库。
其中聚合根可以被认为是"父",并且"子"不能没有父而存在。
在您的示例中,Author是聚合根,因为如果没有Author, Book就不可能存在。(FK证明了这一点)
因此,您应该只拥有一个LibraryRepository,它能够使用单个实体框架对象集同时处理作者和图书。
我们实际上通过将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
)。
然而,看看找一本书是多么的混乱。如果您发现自己需要自己查找"子"(例如,不首先检索父),那么您应该考虑也创建一个图书存储库。
可以归结为两件事:
- 强制聚合边界
- 创建为应用程序服务的存储库
考虑用户界面,每个屏幕需要什么信息,它手头有什么信息来识别那块信息(例如URL)
我会从单元测试的角度来看待它。哪种方法更容易测试控制器并验证代码中的测试结果?