Форум программистов, компьютерный форум, киберфорум
Наши страницы
C#: ASP.NET MVC
Войти
Регистрация
Восстановить пароль
 
DenKG
5 / 5 / 7
Регистрация: 23.12.2015
Сообщений: 734
1

Как во View вывести связанные записи?

06.01.2019, 23:34. Просмотров 210. Ответов 13
Метки нет (Все метки)

У меня есть такие классы:
C#
1
2
3
4
5
6
public class Book
    {
        public int Id { get; set; }
        public string BookName { get; set; }
        public string BookAuthor { get; set; }
    }
C#
1
2
3
4
5
6
public class Student
    {
        public int Id { get; set; }
        public string StudentName { get; set; }
        public int StudentAge { get; set; }
    }
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    public class Rent
    {
        public int Id { get; set; }
        public int StudentId { get; set; }
        public int BookId { get; set; }
        public string RentDate { get; set; }
 
        public ICollection<Book> Books { get; set; }
        public ICollection<Student> Students { get; set; }
 
        public Rent()
        {
            Books = new List<Book>();
            Students = new List<Student>();
        }
    }
И такой контекст:
C#
1
2
3
4
5
6
7
8
9
10
    public class RentContext : DbContext
    {
        public RentContext()
            : base("DbConnection")
        {
            Database.SetInitializer(new RentDbInitializer());
        }
 
        public DbSet<Rent> Rents { get; set; }
    }
Контроллер:
C#
1
2
3
4
public ActionResult Index()
        {
            return View(db.Rents.Include(b => b.Books).Include(s => s.Students).ToList());
        }
Представление:
HTML5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.StudentId)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.BookId)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.RentDate)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.Id }) |
            @Html.ActionLink("Details", "Details", new { id=item.Id }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.Id })
        </td>
    </tr>
}
Как мне здесь вывести не StudentId и BookId, а StudentName и BookName?
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
06.01.2019, 23:34
Ответы с готовыми решениями:

Как удалить записи из таблицы связанные с другой таблицей?
Добрый день! Подскажите пожалуйста с такой штукой: есть в БД две таблицы: Users и Cars. В таблице...

Как вывести связанные данные из модели?
Есть модель public class Game { public int Id { get; set; } public string...

Как прочитать параметры из обычного txt-шника и вывести на View
Господа, встал в ступор: как прочитать параметры из обычного txt-шника и вывести на View? ...

Как вывести на View информацию об объявлении и авторе этого объявления
Помогите разобраться, как вывести на вьюхе информацию об объявлении и авторе этого объявления. ...

Как передать параметры из одного View в EditorFor другого View
Здравствуйте. Есть 2 view, первое просто отображает данные, 2 должно их редактировать, в 1 view...

13
IamRain
1407 / 1254 / 395
Регистрация: 02.08.2011
Сообщений: 3,723
07.01.2019, 00:39 2
Razor - это рендеринг на сервере, раз вы загрузили через Include ваших студентов и книги, то и обращаться уже к ним можно во вьюхе.

Я бы сделал отдельно вьюхи для студента и книги и передавал бы в них в вашей вьюхе.
0
DenKG
5 / 5 / 7
Регистрация: 23.12.2015
Сообщений: 734
07.01.2019, 00:42  [ТС] 3
IamRain, вы имеете ввиду item.Students.StudentName?
0
IamRain
1407 / 1254 / 395
Регистрация: 02.08.2011
Сообщений: 3,723
07.01.2019, 01:47 4
Что-то у вас модель не совсем корректная. По идее если имеются свойства BookId и StudentId, то это FK со стороны many в отношении one-to-many. Но в это же время в сущности имеются коллекции объектов Book и Student.

Надо бы вам подумать и переделать ятп.

А пока предлагаю создать ViewModel - RentListItemViewModel:
C#
1
2
3
4
5
6
7
8
9
10
11
12
public class RentListItemViewModel
    {
        public RentListItemViewModel(int id, Book book, Student student, string rentDate) {
            // Тут записываем свойства
        }
 
        public int Id { get; set; }        
        public string RentDate { get; set; }
 
        public Book Book { get; set; }
        public Student Student { get; set; }        
    }
И передавать примерно так:
C#
1
2
3
4
5
6
7
8
9
10
11
public ActionResult Index()
        {
            var rents = db.Rents.Include(b => b.Books).Include(s => s.Students).ToList();
             var viewModels = rents.Select(r => {
                     var b = r.Books.Single(b => b.Id.Equals(r.BookId));
                     var s = r.Students.Single(s => s.Id.Equals(r.StudentId));
                      return new RentListItemViewModel(r.Id, b, s, r.RentDate);
            });
 
            return View(viewModels);
        }
У вас некорректно спроектирована БД - переделайте и вышеуказанный код не понадобится.
0
DenKG
5 / 5 / 7
Регистрация: 23.12.2015
Сообщений: 734
07.01.2019, 10:32  [ТС] 5
IamRain, так у меня же many-to-many

Добавлено через 36 минут
IamRain, кажется, я понял, что вы имели ввиду.
Т.е. мне модели нужно было переделать следующим образом?
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Student
    {
        public int Id { get; set; }
        public string StudentName { get; set; }
        public int StudentAge { get; set; }
 
        public ICollection<Book> Books { get; set; }
 
        public Student()
        {
            Books = new List<Book>();
        }
    }
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Book
    {
        public int Id { get; set; }
        public string BookName { get; set; }
        public string BookAuthor { get; set; }
 
        public ICollection<Student> Students { get; set; }
 
        public Book()
        {
            Students = new List<Student>();
        }
    }
Добавлено через 14 минут
IamRain, правда, теперь в BookController у меня вылетает такая ошибка:
System.NotSupportedException: "Model compatibility cannot be checked because the database does not contain model metadata. Model compatibility can only be checked for databases created using Code First or Code First Migrations."
Вот тут:
C#
1
2
3
4
public ActionResult Index()
        {
            return View(db.Books.ToList());
        }
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
    public class BookContext : DbContext
    {
        public BookContext()
            : base("DbConnection")
        {
            Database.SetInitializer(new BookDbInitializer());
        }
 
        public DbSet<Book> Books { get; set; }
    }
 
    public class BookDbInitializer : DropCreateDatabaseIfModelChanges<BookContext>
    {
        protected override void Seed(BookContext db)
        {
            db.Books.Add(new Book { BookName = "Война и мир", BookAuthor = "Л.Н.Толстой" });
            db.Books.Add(new Book { BookName = "Три мушкетера", BookAuthor = "А.Дюма" });
            db.Books.Add(new Book { BookName = "Идиот", BookAuthor = "Ф.М.Достоевский" });
            db.SaveChanges();
        }
    }
0
sau
2021 / 1634 / 271
Регистрация: 22.07.2011
Сообщений: 6,205
Завершенные тесты: 1
07.01.2019, 12:44 6
Цитата Сообщение от DenKG Посмотреть сообщение
так у меня же many-to-many
Одна книга не может быть у нескольких студентов ) , а вот студент может иметь множество книг , связь многое-к-одному.
Однако , если книга может быть не только у студента , но и у других людей , тогда потребуются связующие таблицы и получим many-to-many как в вашем первом варианте.
- но это накладно , для каждой категории арендаторов создавать свою структуру , потому как при учете не важно какая категория взяла книгу , студент , учитель или еще кто , достаточно хранить FIO арендатора ну и комментарий к нему - в котором указать всю доп.инфу.

C#
1
2
3
4
5
6
7
8
9
 public class BookRent
    {
        //public int Id { get; set; } - не требуется , одну книгу можно арендовать единожды , т.е BookId ключевое поле.
        [Key]
        public int BookId { get; set; }
        public string FIO {get;set;} // кто взял
        public string Comment {get;set;}
        public string RentDate { get; set; }
    }
0
DenKG
5 / 5 / 7
Регистрация: 23.12.2015
Сообщений: 734
07.01.2019, 13:02  [ТС] 7
sau, так как мне всё таки вывести это всё, если я всё же сделал много-ко-многим?)
0
IamRain
1407 / 1254 / 395
Регистрация: 02.08.2011
Сообщений: 3,723
07.01.2019, 13:34 8
У вас EF Core?
В EF Core many-to-many правильно делать так.
0
DenKG
5 / 5 / 7
Регистрация: 23.12.2015
Сообщений: 734
07.01.2019, 13:38  [ТС] 9
IamRain, нет, .net
0
IamRain
1407 / 1254 / 395
Регистрация: 02.08.2011
Сообщений: 3,723
07.01.2019, 13:56 10
Все таки я бы сделал так:
1. Студент может несколько раз брать книги из библиотеки. То есть:
Student -> Rent = one to many
2. В каждый поход в библиотеку можно брать несколько книг, и в то же время каждую книгу очевидно можно взять несколько раз. То есть:
Rent -> Book = many to many

Соответственно модели:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class Book
    {
        public int Id { get; set; }
        public string BookName { get; set; }
        public string BookAuthor { get; set; }
        public List<BookRent> Rents = new List<BookRent>();
    }
 
public class BookRent
    {
        public int BookRentId { get; set; } // это нужно
        
        public int IdStudent { get; set; }
        
        public string RentDate { get; set; }
 
        public virtual Student Student {get;set;}
 
        public virtual List<Book> Books { get; set; }  = new List<Book>();        
    }
 
 
 
public class Student
    {
        public int Id { get; set; }
        public string StudentName { get; set; }
        public int StudentAge { get; set; }
        public virtual List<BookRent> Rents { get; set; } = new List<BookRent>();
    }
Цитата Сообщение от DenKG Посмотреть сообщение
Model compatibility cannot be checked because the database does not contain model metadata. Model compatibility can only be checked for databases created using Code First or Code First Migrations."
Либо сделайте миграцию, либо удалите базу и запустите проект снова.
0
sau
2021 / 1634 / 271
Регистрация: 22.07.2011
Сообщений: 6,205
Завершенные тесты: 1
07.01.2019, 19:58 11
IamRain, это как так книгу можно взять несколько раз ? )
- тут речь же не про историю пользования , а по текущему положению дел - у кого книга , а значит взять ее можно только один раз. Разные книги . разумеется , можно хранить у разных студентов.
0
DenKG
5 / 5 / 7
Регистрация: 23.12.2015
Сообщений: 734
07.01.2019, 20:00  [ТС] 12
sau, да нет, не стоит сейчас с этим заморачиваться. Это всё было лишь для изучения того, как организовать взаимодействие с данными )
0
IamRain
1407 / 1254 / 395
Регистрация: 02.08.2011
Сообщений: 3,723
07.01.2019, 20:08 13
Цитата Сообщение от sau Посмотреть сообщение
IamRain, это как так книгу можно взять несколько раз ? )
Ну книгу взял, почитал месяцок, потом вернул, потом другой взял... У вас такого не было в университете?)
Я именно про историю, которая также может отражать и текущее состояние. Конкретных требований никто не говорил, так что то, что пришло в голову.

Там и временной срез делается, я бы еще срок чтения/пользования добавил + дату фактической сдачи книги, + вычисляемое время просрочки книги.
0
sau
2021 / 1634 / 271
Регистрация: 22.07.2011
Сообщений: 6,205
Завершенные тесты: 1
07.01.2019, 20:14 14
Цитата Сообщение от DenKG Посмотреть сообщение
как организовать взаимодействие с данными )
ну так взаимодействие будет разным , в зависимости от структуры данных.
и в зависимости от структуры связей , класс либо будет содержать автоматически заполняемую виртуальную коллекцию , либо нет. Но , как бы там ни было , всегда можно можно запросить связанную по внешнему ключу коллекцию данных.
Что касается вьюхи , запрашиваете все нужные данные , запихиваете их в класс RendViewModel - который будет отличным от модели данных т.к решает задачу представления данных для интерфейса.

Добавлено через 4 минуты
Цитата Сообщение от IamRain Посмотреть сообщение
Там и временной срез делается, я бы еще срок чтения/пользования добавил + дату фактической сдачи книги, + вычисляемое время просрочки книги.
все конечно от постановки зависит , потому как исторические таблицы обычно перегружены данными и не подходят для частого использования , мильон записей и запросы длятся долго , нужен специфичный интерфейс с поиском , автоматическое удаление т.к вручную никто не будет чистить историю (и это точно не @foreach (var item in Model)) и т.п и т.д.
Т.е обычно делают hot таблицу для ежедневного пользования , а потом складируют из нее данные в таблицу истории на всякий случай по факту удаления записей.

П.С Ладно , оставим , без меня тут пообщайтесь , я так просто , влез не в тему ).
0
07.01.2019, 20:14
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
07.01.2019, 20:14

Вылезает ошибка при записи данных в Базу после рендеренга View
Всем привет! У меня такая странная проблема: Я пишу данные в базу MSSQL (При помощи Entity...

Как вывести по одной записи из БД?
Как вывести по одной записи из БД. Пр: Есть Recordset (SELECT * FROM table). В нем есть 10...

Вывести содержимое List во view
Каким образом можно вывести выборку на основе модели данных. но с полями в ней не описанными?...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru