C# Entity FrameWork. Добавление записи в БД при отношении один ко многим и многие ко многим

226
21 февраля 2018, 07:34

Здравствуйте всем. Помогите мне, пожалуйста, разобраться наконец-то с добавлением записей в БД при отношении один-ко-многим и многие-ко-многим. Использую технологию Entity Framework, подход проектирования приложения Model-First, не использую паттерн MVVM. Заранее прошу прощения за такой длинный пост и прошу вас отнестись к этому вопросу серьёзно, поскольку я на этот вопрос потратил 2 недели и до сих пор не могу решить этот вопрос из-за того, что нет нигде нормального адекватного источника информации о том, как же всё-таки правильно выполнять CRUD операции.

Вопросы:

  1. Как всё-таки правильно делать добавление записи в БД в отношении многие-ко-многим?
  2. Правильно ли реализован алгоритм добавления записи в БД в отношении один-ко-многим или я где-то в чём-то неправ?
  3. Мне не совсем понятно, зачем в модели БД нужны Свойства навигации? Они появляются при создании Ассоциации между сущностями в Модели БД, а вот как их грамотно использовать в Code-Behind я не знаю.

Внизу предоставлена моя модель приложения:

Внизу предоставлены сгенерированные автоматически классы после сохранения созданной модели при Model-First проектировании:

public partial class Catalog
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public Catalog()
    {
        this.Books = new HashSet<Book>();
    }
    public System.Guid Id { get; set; }
    public string Name { get; set; }
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<Book> Books { get; set; }
}

public partial class Book
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public Book()
    {
        this.Orders = new HashSet<Order>();
    }
    public System.Guid Id { get; set; }
    public string Name { get; set; }
    public string Genre { get; set; }
    public string Author { get; set; }
    public short Year { get; set; }
    public virtual Catalog Catalog { get; set; }
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<Order> Orders { get; set; }
}

public partial class Order
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public Order()
    {
        this.Books = new HashSet<Book>();
    }
    public System.Guid Id { get; set; }
    public string Number { get; set; }
    public Nullable<System.DateTime> RegisteredOn { get; set; }
    public Nullable<System.DateTime> ClosureDate { get; set; }
    public virtual Reader Reader { get; set; }
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<Book> Books { get; set; }
}

public partial class LibraryModelContainer : DbContext
{
    public LibraryModelContainer()
        : base("name=LibraryModelContainer")
    {
    }
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        throw new UnintentionalCodeFirstException();
    }
    public virtual DbSet<Book> Books { get; set; }
    public virtual DbSet<Catalog> Catalogs { get; set; }
    public virtual DbSet<Order> Orders { get; set; }
    public virtual DbSet<Reader> Readers { get; set; }
}

Теперь нужно оговориться, что я в своём приложении в отдельных окнах осуществляю добавление записей в БД. Также я не показываю всю свою логику по добавлению записи, чтобы максимально сократить свой пост, показываю только основную часть.

Отношение между сущностями Каталог и Книга — один-ко-многим

1. Добавление каталога в БД:

using (LibraryModelContainer dbContainer = new LibraryModelContainer())
{
    Catalog catalog = new Catalog
    {
        Id = Guid.NewGuid(),
        Name = CatalogTextBox.Text
    };
    dbContainer.Catalogs.Add(catalog);
    dbContainer.SaveChanges();
}

2. Добавление книги в БД:

using (LibraryModelContainer dbContainer = new LibraryModelContainer())
{
    Catalog catalog = dbContainer.Catalogs.Find(((Catalog)BookCatalogComboBox.SelectedItem).Id);
    Book book = new Book
    {
        Id = Guid.NewGuid(),
        Name = BookAuthorTextBox.Text,
        Genre = BookGenreComboBox.Text,
        Author = BookAuthorTextBox.Text,
        Year = Convert.ToInt16(BookYearMaskedTextBox.Text),
        Catalog = catalog
    };
    dbContainer.Books.Add(book);
    dbContainer.SaveChanges();
    _window.BookDataGrid.ItemsSource = dbContainer.Books.ToList();
}

Отношение между сущностями Книга и Заказ — многие-ко-многим

1. Добавление книги в БД:

Пример показал выше!

2. Добавление заказа в БД:

using (LibraryModelContainer dbContainer = new LibraryModelContainer())
{
    Reader reader = dbContainer.Readers.Find(((Reader)ReaderNameComboBox.SelectedItem).Id);
    ICollection<Book> books = new List<Book>();
    foreach (Book book in BasketBookDataGrid.Items)
    {
        books.Add(book);
    }
    Order order = new Order
    {
        Id = Guid.NewGuid(),
        Number = "НОМЕР123",
        RegisteredOn = DateTime.Now,
        ClosureDate = null,
        Reader = reader,
        Books = books
    };
    dbContainer.Orders.Add(order);
    dbContainer.SaveChanges();
    _window.OrderDataGrid.ItemsSource = dbContainer.Orders.ToList();
}

Тут нужно оговориться, что у меня в окне есть BasketDataGrid. Отдельной таблицы в БД под неё нет. Код BasketGrid в XAML разметке:

<DataGrid Name="BookDataGrid">
    <DataGrid.Columns>
        <DataGridTextColumn Binding="{Binding Name}" Header="Название" MinWidth="114"></DataGridTextColumn>
        <DataGridTextColumn Binding="{Binding Genre}" Header="Жанр" MinWidth="114"></DataGridTextColumn>
        <DataGridTextColumn Binding="{Binding Author}" Header="Автор" MinWidth="114"></DataGridTextColumn>
        <DataGridTextColumn Binding="{Binding Year}" Header="Год издания" MinWidth="114"></DataGridTextColumn>
    </DataGrid.Columns>
</DataGrid>

Метод добавления книг в BasketDataGrid:

private void AddBookToTheBasket_Click(object sender, RoutedEventArgs e) // Добавление книг в корзину заказа
{
    using (LibraryModelContainer dbContainer = new LibraryModelContainer())
    {
        Book book = dbContainer.Books.Find(((Book)BookDataGrid.SelectedItem).Id);
        if (book != null) // Если в DataGrid книг выбрана строка
        {
            BasketBookDataGrid.Items.Add(book);
        }
        else // Если в DataGrid книг ничего не выбрано
        {
            MessageBox.Show("В таблице книг не выбрана книга.");
        }
    }
}

Собственно говоря, когда пытаюсь осуществить добавление записей в отношении к сущностям многие-ко-многим, у меня возникает такая ошибка:

Не совсем понятно, при чём тут название ассоциации CatalogBook в моей модели и почему VS на неё ругается. Добавление записей в отношение один-ко-многим у меня корректно происходит, возможно я не прав, лучше поправьте меня, если ошибаюсь. Но тем не менее в БД в плане ID всё хорошо у меня:

Но, меня настораживает одно: в отладчике, когда смотрю на свойства объектов книги, почему-то свойство Catalog имеет значение null, но такого быть не может вообще, поскольку при добавлении в отношении один-ко-многим я это на 100% проверил и там всё хорошо. Вот скриншот объекта книги, где я синим цветом обвёл свойство Catalog.

READ ALSO
Вопрос о postgressql + C#

Вопрос о postgressql + C#

Использую базу данных postgres, в ней 10 таблиц и в каждой около миллиона записейВсе таблицы связаны с вызовами и имеют уникальный md5

220
SQL Выборка в начале по id, потом по имени

SQL Выборка в начале по id, потом по имени

Подскажите пожалуйстаНужно выбрать с БД MySQL сначало по id, потом по поиску из textbox

158
Что представляет собой тип System.Linq.Enumerable.WhereSelectArrayIterator&lt;T1,T2&gt;?

Что представляет собой тип System.Linq.Enumerable.WhereSelectArrayIterator<T1,T2>?

Изучая LINQ наткнулся на то, что результат запроса имеет такой тип, но информации по нему найти не удалось

231
Инъекция DetailRow внутрь ItemTemplate

Инъекция DetailRow внутрь ItemTemplate

Имеется табличка:

156