Я использую Entity Framework 4 с шаблоном генерации кода POCO от Microsoft, загруженным из галереи Visual Studio. Я также оставляю параметр по умолчанию «Включить внешние ключи в модель», выбранный при создании модели EF из базы данных.
Мне удалось воспроизвести эту проблему с очень простой моделью, состоящей только из двух таблиц / классов в необязательном отношении «один ко многим». В этом случае я использую адрес и человека. Человек может иметь один или ноль адресов, а Адрес может иметь ноль для многих людей.
Таблицы выглядят так:
CREATE TABLE [dbo].[Person](
[PersonID] [uniqueidentifier] NOT NULL,
[FirstName] [nvarchar](50) NULL,
[LastName] [nvarchar](50) NULL,
[AddressID] [uniqueidentifier] NULL,
CONSTRAINT [PK_Person] PRIMARY KEY CLUSTERED ([PersonID] ASC )
CREATE TABLE [dbo].[Address](
[AddressID] [uniqueidentifier] NOT NULL,
[Street1] [nvarchar](50) NOT NULL,
[Street2] [nvarchar](50) NULL,
[City] [nvarchar](50) NOT NULL,
[State] [char](2) NOT NULL,
[Country] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_Address] PRIMARY KEY CLUSTERED ([AddressID] ASC)
ALTER TABLE [dbo].[Person] WITH CHECK ADD CONSTRAINT [FK_Person_Address]
FOREIGN KEY([AddressID])
REFERENCES [dbo].[Address] ([AddressID])
Когда я пытаюсь создать объект Address и добавить его в существующий объект Person, извлеченный из базы данных, я получаю исключение нулевой ссылки:
TestPOCOEntities ctx = new TestPOCOEntities();
var person = ctx.People.FirstOrDefault(p => p.PersonID == new Guid("58AD37B4-1EBE-4649-940C-A141732C9901"));
var addr = new Address {AddressID = Guid.NewGuid(), Street1 = "123 Main St"};
person.Address = addr; // This line throws the exception
ctx.SaveChanges();
При копании в стек вызовов исключение выдается не из моего кода или даже сгенерированного шаблоном кода, а внутри динамического прокси-сервера времени выполнения для класса Person в установщике AddressID
. (В частности, метод System.Data.Objects.EntityEntry.FixupEntityReferenceByForeignKey(EntityReference reference)
.)
Это исключение не возникает, если я использую генерацию кода EF по умолчанию вместо шаблона POCO. Это также не происходит, если я использую шаблон POCO, но сниму флажок «Включить внешние ключи в модель» при создании модели из базы данных.
Я могу устранить ошибку, если добавлю следующее:
var addr = new Address {AddressID = Guid.NewGuid(), Street1 = "123 Main St"};
ctx.Addresses.AddObject(addr); // Adding this line...
person.Address = addr; // Means no more exception here!
Я не понимаю, почему сочетание использования шаблона POCO и включения внешних ключей в модель требует такого изменения кода при взаимодействии с моими постоянными объектами. Это известная ошибка? Я что-то пропустил? Это по какой-то причине задумано?