Просто гипотетическое объяснение:
В примере MusicStore используется разработка Entity Framework Code-First.И он не имеет никакой специальной конфигурации, ни с атрибутами первого кода в модельных классах, ни с использованием плавного API.
Это означает, что EntityFramework выводит структуру базы данных и все отношения полностью из набора соглашенийкоторые определяются за кулисами и основаны на именах классов и свойств классов моделей.
Важными классами для ошибочного запроса являются (упрощенно, только соответствующие свойства):
public class Genre
{
public int GenreId { get; set; }
public string Name { get; set; }
public List<Album> Albums { get; set; }
}
public class Album
{
public int AlbumId { get; set; }
public int GenreId { get; set; }
public virtual Genre Genre { get; set; }
}
И DbContext:
public class MusicStoreEntities : DbContext
{
public DbSet<Album> Albums { get; set; }
public DbSet<Genre> Genres { get; set; }
// other sets...
}
Теперь, благодаря свойству Genre
в классе Album
и коллекции Albums
в классе Genre
Entity Framework знает, что существует Oneотношение-ко-многим между Genre
и Album
, которое отображается в базе данных как отношение внешнего ключа: таблица Albums
должна иметь внешний ключ к таблице Genres
.Теперь EF должен выяснить, как называется этот внешний ключ, чтобы генерировать правильные операторы SQL.Наша модель не определяет имя внешнего ключа явно (что также возможно), поэтому EF следует ряду соглашений, которые в этом случае:
Имеет класс Album
иметь свойство с именем
[имя свойства навигации до целевого класса] + [имя имени свойства первичного ключа в целевом классе]
В нашем случае это будет [Жанр] + [GenreId] = GenreGenreId
-> Нет, у нас такого свойства нет.
Имеет ли класс Album
свойство с именем
[nameцелевого класса] + [имя имени свойства первичного ключа в целевом классе]
Опять в нашем случае это будет [Genre] + [GenreId] = GenreGenreId
-> Нет, у нас нет такогосвойство.
Имеет ли класс Album
свойство с именем
[имя имени свойства первичного ключа в целевом классе]
Inв нашем случае это будет [GenreId] = GenreId
-> Да, у нас есть такое свойство в Album
.
Итак, Entity Framework будетпредположим, что имя внешнего ключа в классе Album
равно GenreId
.И схема базы данных в БД, которая поставляется с образцом MVCMusicStore, действительно имеет такую связь столбца и внешнего ключа.
Итак, наш запрос должен работать.
Но что произойдет, еслимы удаляем public int GenreId { get; set; }
из класса Album
или пишем его неправильно ("GenresId" или что-то в этом роде)?Ни одно из трех приведенных выше правил соглашения не будет применяться, и EF предполагает, что у нашего модельного класса нет свойства, представляющего внешний ключ отношения.Но все равно предполагается, что есть связь (из-за свойств навигации).Для генерации операторов SQL, в которых используются эти отношения, EF должен принять любое имя столбца внешнего ключа в БД.И для этого предположения он следует первому из трех приведенных выше правил, поэтому он предполагает, что имя внешнего ключа GenreGenreId
- но в схеме базы данных это имя GenreId
-> Boom!
Итак, окончательныйвопрос: есть ли у класса Album
в примере, который вы запускаете, свойство GenreId
?(Я видел, что MusicStore имеет несколько примеров шагов, и не во всех из них Album
имеет это свойство.)
(Если оно определенно имеет такое свойство, забудьте этот пост.)
Edit :
GenreId
in Genre
и GenreId
in Album
должны иметь один и тот же тип, в противном случае приведенное выше правило третьего соглашения не применяется.В вашем примере у вас есть разные типы (Int16
и Int32
).Это может быть проблемой.