Как установить связь (0,N:1,1) с EF Core?

Проблема в том, что «у автора может не быть книг или много, но книга никогда не написана двумя или более авторами».

public Author(Document cpf, string name, DateTime birthdate)
        {
            Cpf = cpf;
            Name = name;
            Birthdate = birthdate;
        }

        public Document Cpf { get; private set; }
        public string Name { get; private set; }
        public DateTime Birthdate { get; private set; }
        // EF Relation
        public Book Book { get; private set; }
        public ICollection<Book> Books { get; private set; }

        protected Author() { }

// 0 : N => Author : Books
            builder.HasMany(c => c.Books)
                .WithOne(b => b.Author)
                .HasForeignKey(b => b.AuthorId);
public Book(Guid categoryId, Guid authorId, string title, DateTime releaseDate, BookIdentificator isbn)
        {
            CategoryId = categoryId;
            AuthorId = authorId;
            Title = title;
            ReleaseDate = releaseDate;
            Isbn = isbn;
        }

        public Guid CategoryId { get; private set; }
        public Guid AuthorId { get; private set; }
        public string Title { get; private set; }
        public DateTime ReleaseDate { get; private set; }
        public BookIdentificator Isbn { get; private set; }
        public Category Category { get; private set; }
        public Author Author { get; private set; }
            // 1 : 1 => Books : Author
            builder.HasOne(c => c.Author)
                   .WithOne(b => b.Book)
                   .HasForeignKey(b => b.AuthorId);

Ошибка: невозможно преобразовать лямбда-выражение в тип «строка», поскольку это не тип делегата BookManager.Catalog.Data


person Thiago Cruz    schedule 22.12.2019    source источник
comment
Не ответ, но у книг часто бывает несколько авторов...   -  person DavidG    schedule 22.12.2019
comment
Не в этом контексте   -  person Thiago Cruz    schedule 22.12.2019
comment
То, что вы описываете, звучит как стандартное отношение «один ко многим» от автора к книге. Каждое отношение один ко многим 1:0..N от X до Y является либо 1:0..1 (необязательно), либо 1:1 (обязательно) от Y до X. Следовательно, свойство Author.Book является избыточным и должно быть удалено. Также вторая беглая конфигурация.   -  person Ivan Stoev    schedule 23.12.2019


Ответы (2)


Это сложная проблема, чтобы помочь вам, потому что вы не опубликовали полный пример своих классов Author или Book, только фрагменты, и эти фрагменты недостаточно полны.

Ваша конкретная ошибка обсуждалась:

Невозможно преобразовать лямбда-выражение в тип "строка", поскольку это не тип делегата

Это вызвано тем, что компилятор ожидает, что вы используете одну из перегрузок для QueryTypeBuilder.HasOne Method и не обнаружив соответствия, по умолчанию используется перегрузка HasOne(string, string). Вы должны использовать методы расширения, чтобы упростить доступ к гибкой конфигурации.

Добавьте операторы использования:

using System.Linq; 
using System.Data.Entity;

Это только начало ваших проблем, а следующая заключается в том, что Author имеет оба следующих свойства:

// EF Relation
public Book Book { get; private set; }
public ICollection<Book> Books { get; private set; }

Здесь вы говорите, что у каждого Автора есть одна конкретная книга И коллекция книг. Не понимая остальной части приложения, это может быть верным, возможно, единственная ссылка на книгу - это биография автора? или их первая книга? в любом случае, если вы хотите, чтобы такие отношения существовали, вам нужно будет использовать беглую нотацию, чтобы конкретно описать конечные точки, используемые для обоих отношений.

Могу ли я вместо этого предложить, что вам нужно только свойство Books в классе Author:

// EF Relation
public virtual ICollection<Book> Books { get; set; } = new HashSet<Book>();

Тогда ваша беглая нотация все еще нуждается в следующей настройке:

Автор

Здесь никаких изменений, этот действителен, с использованием более длинных имен переменных, чтобы помочь объяснить взаимосвязь.

Вы не должны обязаны сокращать имена переменных в операторах linq до одного символа, но если вы это сделаете, используйте первый символ концептуального имени или типа переменной, чтобы его было легче читать и просматривать. ожидания кода.

// 0 : N => Author : Books
builder.HasMany(author => a.Books)
       .WithOne(book => book.Author)
       .HasForeignKey(book => book.AuthorId);

Книга

В исходном коде ОП неправильно указал, что соотношение Book:Author было 1:1, хотя на самом деле оно равно Many:1.

// N : 1 => Books : Author
builder.HasOne(book => book.Author)
       .WithMany(author => author.Books)
       .HasForeignKey(book => book.AuthorId);

ПРИМЕЧАНИЕ. Хотя вы можете указать каждую связь в прямой или обратной логике, необходимо указать каждую связь только один раз с помощью беглой нотации.

  • Необходимо определить только одну из приведенных выше конфигураций, обе они описывают одну и ту же ссылку.

Та же самая конфигурация могла бы быть достигнута с нотацией атрибута в классе Book:

[ForeignKey(nameof(AuthorId))]
public virtual Author Author { get; set; }

Последнее замечание о моем стиле кода: я рекомендую объявить все свойства навигации виртуальными, чтобы облегчить ленивую загрузку и оптимизировать отслеживание изменений.

Кроме того, все свойства коллекции должны быть автоматически инициализированы с помощью new HashSet<T>(), чтобы уменьшить объем кода, который необходимо написать для создания объектов во время выполнения и для поддержки связанных операций с данными.

person Chris Schaller    schedule 22.12.2019
comment
На самом деле public Book Book {get; private set; } не нужен. Настройка // 1: 1 => Books: Author требуется, если я делаю public virtual ICollection <Book> Books {get; set; } = new HashSet <Book> (); ? - person Thiago Cruz; 23.12.2019
comment
Я подозреваю, что public Book Book {get; private set; } - это ошибка, ее вообще не должно быть, если вы не можете объяснить ее бизнес-причину. Это не имеет ничего общего с отношениями, которые вы описали: Author имеет набор Books, Book имеет один Author. - person Chris Schaller; 23.12.2019
comment
Рассматривая ситуацию, реальные отношения таковы, что у одной книги один автор, а у одного автора - N книг. - person Thiago Cruz; 23.12.2019
comment
Абсолютно, извините, я забыл указать это в своем решении, я обновил свой ответ. - person Chris Schaller; 23.12.2019

Не вижу никаких проблем с вашим кодом. Может быть, вам не хватает только оператора using? Невозможно преобразовать лямбда-выражение ввести 'string', потому что это не тип делегата

person Peter Sandor    schedule 22.12.2019
comment
К сожалению, это не так, потому что в другом отображении я его не использую, и он работает правильно. - person Thiago Cruz; 22.12.2019
comment
Да @panoskarajohn ! - person Thiago Cruz; 23.12.2019
comment
@ThiagoCruz, не могли бы вы указать нам, где вы видите ошибку в своем коде? - person panoskarajohn; 23.12.2019
comment
В этом конструкторе // 1 : 1 =› Книги : Автор, в этой строке .HasForeignKey(b => b.AuthorId);. Эта ошибка возникает «Невозможно преобразовать лямбда-выражение в тип« строка », потому что это не тип делегата BookManager.Catalog.Data». - person Thiago Cruz; 23.12.2019