Entity Framework CTP 4. "Невозможно вставить значение NULL в столбец" - даже если значение NULL отсутствует
Я использую EF CTP 4. У меня есть простое консольное приложение (для тестирования), которое использует EF для вставки некоторых данных в базу данных SQL.
Я столкнулся с проблемой, когда при вставке элемента
using(var context = GetContext())
{
BOB b = new BOB();
b.Id = 1;
context.Bobs.Add(b);
context.SaveChanges();
}
Он выдает ошибку: {"Невозможно вставить значение NULL в столбец" Id ", таблица" TestDB.dbo.BOB "; столбец не допускает нулевые значения. INSERT завершается неудачей.\ R \n Определение завершено."}
В таблице есть только 1 поле Id int NOT NULL, которое является первичным ключом и не является автоматически увеличенным идентификатором.
При создании DataContext у меня есть эта конфигурация, которая да уволен.
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<BOB>().HasKey(b => b.Id);
builder.Entity<BOB>().MapSingleType().ToTable("BOB");
}
Я также предварительно заполнил эту таблицу, а затем через отладчик смог через часы загрузить этот объект BOB... так что я действительно озадачен, так как возможность загрузить мой BOB показывает, что все правильно... однако при вставке нового он вылетает...
10 ответов
Вы пытались явно указать StoreGeneratedPattern
?
modelBuilder.Entity<BOB>()
.HasKey(p => p.Id)
.Property(p => p.Id)
.StoreGeneratedPattern = StoreGeneratedPattern.None;
builder.Entity<BOB>().MapSingleType().ToTable("BOB");
У меня та же проблема, и это действительно ужасное решение.
[Key]
public Int64 PolicyID { get; set; }
это НЕ автоматически сгенерированный номер
тогда я попал в ту же ошибку.
EF Code First CTP5
после применения этого:
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public Int64 PolicyID { get; set; }
тогда это будет работать.
Я пользуюсь EF 4.1, Model First и столкнулся с этой проблемой. Вот как я это решил:
При использовании поверхности конструктора моделей при создании сущности необходимо определить свойство "Ключ", по умолчанию используется Id, int32.
В моей ситуации я решил использовать Guids для Id, поэтому я переключил int32 на Guid. Но если вы изучите этот идентификатор после создания сущности, я обнаружил, что в идентификаторе StoreGeneratedPattern для этого идентификатора выбрано "удостоверение личности". Сначала я не думал, что это было проблемой, но когда я изучил SQL, используемый для вставки в базу данных, было немного странно, что он не отправлял мой идентификатор. Срыв!
Но как только я вернулся и изменил "StoreGeneratedPattern" с "identity" на "none", заново сгенерировал db и перестроил проект, это странное {"Невозможно вставить значение NULL в столбец" Id ", таблица" TestDB.dbo.BOB ". '; столбец не допускает пустых значений. INSERT завершается неудачей.\r\n Описание завершено."} перестал выполняться.
К вашему сведению - при просмотре sql еще кажется, что если вы выбрали "identity" для "StoreGeneratedPattern", EF сохраняет объект в db (sans Id), а затем немедленно возвращает идентификатор и сохраняет его обратно в ваш объект. т. е. этот выбор для StoreGeneratedPattern основан на БД для генерации вашего идентификатора, а не кода!
Вы также можете использовать
modelBuilder.Entity<BOB>()
.HasKey(p => p.Id)
.Property(p => p.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
builder.Entity<BOB>().MapSingleType().ToTable("BOB");
Это случилось со мной, когда у меня отсутствовал первичный ключ в соответствующем столбце (столбце идентификаторов) в схеме базы данных. Я экспортировал данные между серверами SQL, используя инструмент экспорта SSMS и создавая новую базу данных, но не осознавал, что она экспортирует только данные без ключей.
У меня была похожая ситуация, но в моем случае даже настройка Identity
в off
не помогло
Проблема была связана с Первичным ключом, который я пропустил, чтобы добавить в мою модель сущности.
Вот скрипт, который генерировал модель:
CREATE TABLE [im].[SomeGroup]
(
[Id] INT NOT NULL IDENTITY(1,1), -- this is mandatory for EF
[OtherGroupId] INT NOT NULL,
[Title] NVARCHAR(512) NOT NULL
)
Код C# для выше:
Insert(new SomeGroup
{
// I'm not providing Id here, cause it will be auto-generated
SomeGroupId = otherGroup.Id,
Title = otherGroup.Title
});
Вот также некоторое объяснение этого.
В моем случае EntityFramework сгенерировал этот код внутри Context.cs
класс:
modelBuilder.Entity<MODEL_OF_TABLE>(entity =>
{
entity.Property(e => e.Id).ValueGeneratedNever(); // <= this line must remove
...
}
после удаления этой строки проблема решена.
Загляните и в эту проблему. Для меня моя таблица Dev DB по какой-то причине не принесла ключ, поэтому EF не определил мой идентификатор как ключ.
Примечание для всех, у кого есть эта проблема: убедитесь, что ваша таблица, в которую вы пытаетесь вставить новую запись с полем идентификатора, действительно определена в вашем классе Context.
modelBuilder.Entity<CustomerEmail>(entity =>
{
entity.HasKey(e => e.Id)
.HasName("PK_tblCustomerEmail");
entity.Property(e => e.Customer).IsUnicode(false);
entity.Property(e => e.Email).IsUnicode(false);
});
Я знаю, что этот вопрос каким-то образом устарел, и приемлемое решение уже найдено, однако я подумал, что будет полезно, если я поделюсь своими выводами.
У меня была эта ошибка сегодня, потому что я использовал два разных экземпляра одного и того же DataContext
, Я создавал новую модель с некоторыми свойствами - значения для этих свойств были загружены из базы данных, используя один экземпляр DataContext
Затем я пытался вставить эту вновь созданную модель в базу данных, вызывая в первую очередь Add()
а потом SaveChanges()
на другом экземпляре DataContext
, После того как я начал использовать один и тот же экземпляр как для получения значений для свойств, так и для добавления и сохранения нового объекта - все стало работать.
Если вы используете первый подход к базе данных, сначала удалите соответствующий объект из диаграммы edmx, а затем обновите модель из базы данных, это обязательно решит вашу проблему.