我正在使用Entity Framework 4和从Visual Studio库下载的Microsoft的POCO代码生成模板。我还从数据库生成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();
深入调用堆栈,异常不会从我的代码,甚至模板生成的代码中抛出,而是在AddressID
setter中Person类的运行时动态代理中抛出。 (具体来说,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模板和在模型中包含外键的组合应该需要这种代码更改。这是一个已知的错误?我错过了什么吗?这是出于某种原因设计的吗?
答案 0 :(得分:0)
这是EF的一个潜在错误,通常会刷新一个创建的实体(用新数据重新保存更改)解决方案:
作弊是首先将实体添加到集合上下文
第二次分配给父实体
第三,通常保存更改!
享受