Entity Framework (4.3) ищет единственное имя вместо множественного числа (когда имя сущности заканчивается на «s») - PullRequest
13 голосов
/ 25 февраля 2012

Вот моя ситуация: Я некоторое время работал над приложением ASP.NET MVC 3. У него есть база данных (построенная из проекта db; я собираюсь сначала db), для которой у меня есть модель edmx, а затем набор POCO. Мои базы данных имеют множественные имена в базе данных, а POCO имеют единичные имена. Все карты красиво без проблем.

Или раньше, пока я не добавил новую таблицу (называемую TransactionStatuses). Теперь все старые сущности все еще работают, а новые - нет. Когда я пытаюсь загрузить его вместе со связанным объектом:

var transactions = (from t in db.Transactions.Include(s => s.TransactionStatus) //TransactionStatus - navigation property in Transactions to TransactionStatuses
                    where t.CustomerID == CustomerID
                    select t).ToList();

Я получаю

Неверное имя объекта 'dbo.TransactionStatus'.

Я даже сделал более простой тест:

List<TransactionStatus> statuses = db.TransactionStatuses.ToList();

= тот же результат.

Я обновил (и даже заново создал) edmx из базы данных и прошел через него взад и вперед, пытаясь выяснить, что отличает отображение для dbo.TransactionStatus * es *, который отключает все дело вверх.

Если бы кто-то мог указать мне в направлении исправления, это было бы замечательно.

P.S. Отключение плюрализации не вариант, спасибо.

Обновление : я понял - мой ответ ниже.

Ответы [ 4 ]

32 голосов
/ 27 февраля 2012

Это, вероятно, происходит потому, что хотя планировалось использовать поток Database First, на самом деле приложение использует Code First для отображения.Позвольте мне объяснить немного больше, потому что это может сбить с толку.: -)

При использовании Database First с EF Designer и шаблонами DbContext в Visual Studio происходят три очень важные вещи.Во-первых, новый мастер Entity Data Model добавляет строку подключения к вашему приложению, содержащую сведения о модели Database First (т.е. EDMX), чтобы при запуске приложения она могла найти эту модель.Строка подключения будет выглядеть примерно так:

<connectionStrings>
    <add name="MyEntities"
    connectionString="metadata=res://*/MyModel.csdl|res://*/MyModel.ssdl|res://*/MyModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=.\sqlexpress;initial catalog=MyEntities;integrated security=True;multipleactiveresultsets=True;App=EntityFramework&quot;"
    providerName="System.Data.EntityClient" />
</connectionStrings>

Во-вторых, сгенерированный класс контекста выполняет вызов базового конструктора DbContext с указанием имени этой строки подключения:

public MyEntities()
: base("name=MyEntities")
{
}

Thisговорит DbContext найти и использовать строку подключения «MyEntities» в конфигурации.Использование «name =» означает, что DbContext сгенерирует, если не найдет строку подключения - он просто не будет создавать соединение по соглашению.

Если вы хотите сначала использовать базу данных, тоВы должны использовать строку подключения, такую ​​как сгенерированная.В частности, он должен содержать данные модели (csdl, msl, ssdl из EDMX), и вы должны убедиться, что DbContext находит их.Будьте очень осторожны при изменении вызова базового конструктора.

Третье, что происходит, - это то, что OnModelCreating переопределяется в сгенерированном контексте и генерирует команду throw:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    throw new UnintentionalCodeFirstException();
}

Это сделано потому, чтоOnModelCreating вызывается только при использовании Code First.Это потому, что OnModelCreating - это все о создании модели, но когда вы используете Database First, модель уже существует - во время выполнения создавать нечего.Поэтому, если вызывается OnModelCreating, то это, вероятно, связано с тем, что вы начали использовать Code First без смысла, обычно из-за изменения строки подключения или обращения к базовому конструктору.

Теперь, возможно, вы захотитеиспользовать Code First для сопоставления с существующей базой данных.Это отличный шаблон, и он полностью поддерживается (см. http://blogs.msdn.com/b/adonet/archive/2011/03/07/when-is-code-first-not-code-first.aspx), но вам необходимо убедиться, что сопоставления настроены надлежащим образом, чтобы это работало. Если сопоставления настроены неправильно, вы получите исключения, подобные приведенному в этом вопросе..

7 голосов
/ 26 февраля 2012

Понял!Ужасный, ужасный опыт ...

Короче говоря: EF не может правильно множить имена сущностей, заканчивающиеся на "s" (например, "status", "campus" и т. Д.)

Вот как я получил это и доказательство.

  • Я несколько раз создавал и воссоздавал свой оригинальный набор с одним и тем же результатом.
  • Я также пытался переименовать свой стол в такие вещи, как TransStatus и тому подобное - не повезло.
  • Пока я занимался этим, я наткнулся на статью о множественном числе Скотта Хансельмана , где он добавил правила множественного числа для таких слов, как sheep и goose.Это заставило меня задуматься: «, что, если у него проблема с фактическим именем сущности? »
  • Я немного искал, в частности, слово status и нашел этот отчетпроблемы на Connect .Я бросился пытаться переименовать мою сущность ...
  • Переименование TransactionStatuses в TransactionStates (при этом даже при сохранении столбцов в StatusID) исправлена ​​проблема !Теперь я могу получить List<TransactionState> statuses = db.TransactionStates.ToList();
  • Я думал, что проблема была в конкретном слове status в названии ... Но после того, как я начал жаловаться на это другу, мне предложили, что, возможно, проблема вслово, оканчивающееся на "s" ... Поэтому я решил проверить его.
  • Я создал другую таблицу с именем Campuses и соответствую POCO Campus (и обновил edmx).Сделал простой тест List<Campus> test = db.Campuses.ToList(); и получил ожидаемое

Неверное имя объекта 'dbo.Campus'.

Итак, вы, могучий EFне может обработать множественное число слов, заканчивающихся на "s".Надеюсь, следующий бедняга, столкнувшийся с проблемой, найдет этот вопрос и избавит его от 3-4 часов боли и разочарования.

0 голосов
/ 15 декабря 2013

Вздох. Тот же тип проблемы с классом и моделью Фото и видео; он ищет таблицу фото и видео. Я ненавижу просто менять имя таблицы, но, похоже, выбор не очень.

0 голосов
/ 25 февраля 2012

Вы упомянули EDMX, но я не могу сказать, выполняете ли вы сначала базу данных с EDMX или сначала с кодом, и просто используете EDMX, чтобы увидеть, что происходит.

Если вы используете Code First, то вы можете использоватьконфигурация для указания имени таблицы.Аннотацией данных является [Table ("TransactionStatuses")], свободно - modelBuilder.Entity (). ToTable ("TransactionStatuses").(Я набираю аннотации и свободный код из памяти, поэтому дважды проверьте ссылки.;))

Если вы сначала используете базу данных, SSDL должен абсолютно точно знать имя таблицы базы данных, поэтому я 'Я предполагаю, что вы сначала используете код, а edmx только для исследования.(???)

hth

...