Это сложная проблема, чтобы помочь вам, потому что вы не опубликовали полный пример ваших классов Author
или Book
, только фрагменты, и эти фрагменты не являются полными.
Ваша конкретная ошибка обсуждалась:
Невозможно преобразовать лямбда-выражение в тип 'string', поскольку оно не является типом делегата
Это вызвано тем, что компилятор ожидает, что вы будете использовать одну из перегрузок для 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
class:
// 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);
Книга
В исходном коде OP неправильно указано, что 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>()
, чтобы уменьшить объем кода, который необходимо написать для создания объектов во время выполнения, и для поддержки операций с цепочками данных.