Entity Framework (4.3) ищет уникальное имя вместо множественного числа (когда имя объекта заканчивается на "s" )
Вот моя ситуация:
Я некоторое время работаю над приложением ASP.NET MVC 3. У этого есть база данных (построенная из проекта db, я иду db-first), для которого у меня есть модель edmx, а затем набор POCOs. Мои объекты имеют множественные имена в базе данных, а POCOs имеют уникальные имена. Все прекрасно выглядит без проблем.
Или используется до тех пор, пока я не добавлю новую таблицу (называемую 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 из db и прошел через него взад и вперед, пытаясь выяснить, что отличается от сопоставления для dbo.TransactionStatus * es *, который совершает все это.
Если кто-то может указать мне в сторону исправления, было бы замечательно.
P.S. Отклонение плюрализации не является вариантом, спасибо.
Обновление: я понял это - мой ответ ниже.
Ответы
Ответ 1
Это, вероятно, происходит потому, что, хотя намерение состояло в использовании потока базы данных First, на самом деле приложение использует Code First для сопоставления. Позвольте мне объяснить немного больше, потому что это может ввести в заблуждение.: -)
При использовании базы данных First с дизайнером EF и шаблонами DbContext в Visual Studio происходят три очень важные вещи. Во-первых, новый мастер модели данных Entity добавляет строку подключения к вашему приложению, содержащую сведения о модели базы данных First (например, EDMX), чтобы при запуске приложения она могла найти эту модель. Строка подключения будет выглядеть примерно так:
<connectionStrings>
<add name="MyEntities"
connectionString="metadata=res://*/MyModel.csdl|res://*/MyModel.ssdl|res://*/MyModel.msl;provider=System.Data.SqlClient;provider connection string="data source=.\sqlexpress;initial catalog=MyEntities;integrated security=True;multipleactiveresultsets=True;App=EntityFramework""
providerName="System.Data.EntityClient" />
</connectionStrings>
Во-вторых, созданный класс контекста вызывает вызов базового конструктора DbContext, определяющего имя этой строки соединения:
public MyEntities()
: base("name=MyEntities")
{
}
Это говорит DbContext, чтобы найти и использовать строку подключения "MyEntities" в конфиге. Использование "name=" означает, что DbContext будет бросать, если он не найдет строку подключения - он не будет просто продолжать и создавать соединение по соглашению.
Если вы хотите использовать Database First, тогда вы должны использовать строку подключения, такую как созданная. В частности, он должен содержать данные модели (csdl, msl, ssdl из EDMX), и вы должны убедиться, что DbContext находит это. Будьте осторожны при изменении вызова базового конструктора.
Третье, что происходит, это то, что OnModelCreating переопределяется в сгенерированном контексте и делается для того, чтобы бросить:
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), но вам нужно убедиться, что сопоставления настроены соответствующим образом, чтобы это работало. Если сопоставления не настроены правильно, вы получите исключения, подобные тем, которые заданы в этом вопросе.
Ответ 2
Получил!
Ужасный, ужасный опыт...
Вкратце: EF не может правильно различать имена объектов, заканчивающиеся на "s" (например, "статус", "кампус" и т.д.)
Вот как я получил это и доказал.
- Я создал и повторно создал свою оригинальную настройку несколько раз с тем же результатом.
- Я также попытался переименовать мою таблицу в такие вещи, как
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 часа от боли и разочарования.
Ответ 3
Вы упоминаете EDMX, но я не могу сказать, сначала ли вы делаете databse сначала с EDMX или кодом, а просто с помощью EDMX, чтобы узнать, что происходит.
Если вы используете Code First, вы можете использовать конфигурацию для указания имени таблицы. Аннотации данных - это [Таблица (TransactionStatuses)], свободно - modelBuilder.Entity(). ToTable ( "TransactionStatuses" ).
(Я набираю аннотацию и свободный код из памяти, поэтому дважды проверяю ссылки.;))
Если вы сначала используете базу данных, SSDL должен абсолютно знать имя таблицы базы данных, поэтому я предполагаю, что вы сначала используете код, а edmx - только для исследования. (???)
HTH
Ответ 4
Вздох. Тот же тип проблемы с классом и моделью Photo and Video; он ищет таблицу фотографий и видео. Мне не нравится просто изменять имя таблицы, но не так много выбора, как выглядит.