In the table itself, the posts have an author column where the id of the author is stored, but the problem is that I don’t understand how to display the author’s name in the view. Rather, I do not understand who should receive this data.
Should the post model itself receive user data or should the controller use two models?
- Use the navigation properties - user218976
2 answers
Not exactly in pseudocode, but I’ll tell you briefly and close to how this is done in PHP's Laravel framework.
The construction of the relationship and the necessary requests are initiated in the base class of the model. If you try to access the $somePost->author attribute, which is just a relationship with another model (There is an author_id column in the author_id , but the author column is missing), it executes the query and gets the associated Author::find($somePost->author_id) data model Author::find($somePost->author_id) , attaching it to the desired attribute of the source model, i.e. in $somePost->author . The source of Laravel itself did not look at this part, but the process is presented in this way. Again, following the paradigm of “thin controller - fat model” it turns out that this bundle is really better to keep at the level of models.
Laravel went even further and added optimization, for cases when you need to pull out posts with authors for output, for example, the index page with all records and their authors. Added eager loading, i.e. you can use something like:
Post::with('author')->all() And thus upload all posts at once with their authors by a much smaller number of requests than if there will be calls to the database for each post.
It is necessary to separate domain models and display models. The hierarchy must be built either by yourself (SQL-JOIN of two tables and filling of entities), or by ORM. The controller should think only about how to interact with the interface, the data access layer is usually responsible for data requests (in the example this is the repository):
Domain entities:
public class Author { public int Id { get; set; } public string Name { get; set; } } public class Post { int Id { get; set; } public string Content { get; set; } public int AuthorId { get; set; } public Author Author { get; set; } } View models:
public class PostViewModel { int Id { get; set; } public string Content { get; set; } public string AuthorName { get; set; } } The controller itself (with model mapping):
public class MyBlogController: Controller { private readonly IPostRepository _postRepository; public MyBlogController(IPostRepository postRepository) { _postRepository = postRepository; } public IActionResult Post(int id) { var post = _postRepository.Get(id); if (post == null) return NotFound(); var model = new PostViewModel{ Id = post.Id, Title = post.Title, Content = post.Content, AuthorName = post.Author.Name }; return View(model); } } And the repository:
public interface IPostRepository { Post Get(int id); } public class PostRepository: IPostRepository { protected readonly BlogDbContext _context; public PostRepository(BlogDbContext context) { _context = context; } Post Get(int id) { return _context.Posts.Include(x => x.Author); } }