您什么时候决定应该创建一个新的存储库?
假设你有这两门课。
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)
}
我希望得到一些有关处理此类情况的建议。 请随意批评我的代码。
请帮忙提前致谢。
附:我正在使用 EF,如果它有什么区别的话。
Say you have these two classes.
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;}
}
If I have a BooksController that has all its actions receive a AuthorId
I go to this address:
/Authors/1/Books
Does it make sense to just use a current AuthorRepository?
public ActionResult Index(int AuthorId)
{
return View(_AuthorRepository.GetById(AuthorId).Books)
}
Or for the sake of keeping data access inside repositories I should create a BookRepository?
public ActionResult Index(int AuthorId)
{
return View(_BookRepository.GetByAuthorId(AuthorId))
}
same thing happens with Create action. I have a hard time deciding which one makes more sense.
[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)
}
Or this approach.
[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)
}
I would appreciate some advice on handling scenarios like this.
Feel free to criticize my code as much as you want.
Please help thanks in advance.
ps. Im using EF, if it makes any difference.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我会在单元测试方面考虑它。哪种方法提供了更简单的方法来测试控制器和验证代码中的测试结果?
I would look at it in unit testing aspect. Which method provides easier way of testing the controllers and of verifying the test results in your code?
一般经验法则是每个聚合根创建一个存储库。
其中聚合根可以被认为是“父级”,并且“子级”不能没有父级而存在。
在您的示例中,作者是聚合根,因为没有作者就不可能存在书籍。 (FK证明了这一点)。
因此,您应该只有一个 LibraryRepository,它能够使用单个实体框架对象集与作者和书籍一起工作。
实际上,我们通过将 ObjectSet 输入到存储库上的通用类型来在存储库中强制执行这些聚合边界。
因此您可能会这样:
在上面的示例中,
_context
是通用存储库中的一个受保护
属性,其类型为ObjectSet
(这是通用存储库中的T
)。然而,看看找书是多么的混乱。如果您发现自己需要自己找到一个“子项”(例如,不首先检索父项),那么您也应该考虑创建一个图书存储库。
因此,它归结为两件事:
考虑用户界面,每个屏幕需要什么信息,它手头有什么信息来识别该信息(例如 URL)。
The general rule of thumb is to create one repository per aggregate root.
Where an aggregate root can be thought of as like a "parent", and a "child" cannot exist without a parent.
In your example, the Author is the aggregate root, because a Book cannot exist without an Author. (the FK proves this).
Therefore, you should just have a LibraryRepository, that is capable of working with both authors and books, with a single Entity Framework objectset.
We actually enforce these aggregate boundaries in our Repository by typing the ObjectSet to the generic type on the Repository.
So you might have:
In the above example,
_context
is aprotected
property in the generic repository, which is typed toObjectSet<Author>
(which isT
on the Generic Repository).However, see how it's kind of messy to find a book. If you find yourself needing to find a "child" on it's own (e.g without retrieving the parent first), then you should consider creating a book repository as well.
So it comes down to two things:
Think about the user interface, what information does each screen need, what information does it have at hand to identify that piece of info (e.g URL).