#c# #entity-framework #linq #lambda
#c# #entity-framework #linq #лямбда
Вопрос:
Моя модель:
public partial class Books
{
public int Id { get; set; }
public string Grade { get; set; }
public string Goal { get; set; }
public int? Subjectid { get; set; }
public DateTime? Createdon { get; set; }
//public string Subjectname { get; set; }
//public virtual ICollection<Subjects> RelatedSubject { get; set; }
public virtual Subjects Subject { get; set; }
Мой контроллер: (webapi)
public async Task<ActionResult<IEnumerable<Books>>> GetBooks()
{
var Books = await _context.Books
.Join(_context.Subjects,
c => c.Subjectid,
s => s.Id,
(c, s) => new Subjects {Id = s.Id, Name = s.Name, })
//(c, s) => new { subjectname = s.Subject, subjectid = s.Id })
.ToListAsync();
return Books;
//return await _context.Books.ToListAsync();
}
Я получаю эту ошибку:
Ошибка CS0029 Не удается неявно преобразовать тип ‘System.Коллекции.Generic.List<MyProject.Subjects>’ to ‘Microsoft.AspNetCore.Mvc.ActionResultКоллекции.Общий.IEnumerableКниги>>’
Когда я вызываю api, я вижу, что Subject является пустым свойством.
Почему он не получит имя объекта из linq / lambda?
Редактировать
После нескольких советов я попробовал это:
var Books = _context.Books.Include("Subjects.Name").ToListAsync();
Исключение InvalidOperationException: недопустимый путь включения: ‘Subjects.Name ‘ — не удалось найти навигацию для: ‘Subjects’
Это связь, которую я должен был добавить? У меня есть перенесенная база данных.
Комментарии:
1. Вы также получаете ошибку, если используете анонимный тип
(c, s) => new {Id = s.Id, Name = s.Name}
? Что говорит ваш отладчик о типах идентификатора и имени? Это те же типы, что иSubjects.Id
иSubjects.Name
?2. Да, затем он говорит, что он не работает с
Task<ActionResult<IEnumerable<Books>>>
3. должно быть
.Include("Subject")
, вы загружаетеSubjects
объект и можете получить к нему доступ следующим образомbooks.Subject.Name
4. Я не согласен с
Include
.Select
Также должен работать. Это будет работать еще быстрее, потому что включение передаст все столбцы таблицы, включая столбцы, которые вы не будете использовать. Используйте Include только в том случае, если вы планируете обновить полученные данные.5. Мой, выполните некоторую отладку: измените, например, код без асинхронного ожидания. Что это говорит? «Это не работает» недостаточно для нас, чтобы обнаружить ваши ошибки.
Ответ №1:
virtual
Ключевое слово необходимо только при использовании отложенной загрузки. Затем свойство загружается при первом обращении (не при чтении данных из базы данных).
Если вы хотите загрузить данные из базы данных, включая некоторые свойства, вам может потребоваться использовать .Include()
расширение
Код может выглядеть так:
public async Task<ActionResult<IEnumerable<Books>>> GetBooks()
{
var books = await _context.Books.Include(nameof(Books.Subject)).ToListAsync();
return books;
}