Entity framework 4 EF4-POCO-SaveChanges意外地复制了查找表中的项

Entity framework 4 EF4-POCO-SaveChanges意外地复制了查找表中的项,entity-framework-4,poco,Entity Framework 4,Poco,我在POCO中使用EF4,下面的代码是我必须更新许可证的代码。我只在这里粘贴了与问题相关的代码部分,即添加LicenseDetails 问题是,对于插入的每个LicenseDetail,EF也意外地将行添加到“Item”查找表中。为什么 数据库(SQLServer2008)中定义的两个表之间的关系如下所示,我首先创建数据库,因此EF基于此生成实体的关系 ALTER TABLE [dbo].[LicenseDetail] WITH CHECK ADD CONSTRAINT [FK_Licen

我在POCO中使用EF4,下面的代码是我必须更新许可证的代码。我只在这里粘贴了与问题相关的代码部分,即添加LicenseDetails

问题是,对于插入的每个LicenseDetail,EF也意外地将行添加到“Item”查找表中。为什么

数据库(SQLServer2008)中定义的两个表之间的关系如下所示,我首先创建数据库,因此EF基于此生成实体的关系

ALTER TABLE [dbo].[LicenseDetail]  
WITH CHECK ADD  CONSTRAINT [FK_LicenseDetail_Item] FOREIGN KEY([ItemId])
REFERENCES [dbo].[Item] ([Id])
GO

ALTER TABLE [dbo].[LicenseDetail] CHECK CONSTRAINT [FK_LicenseDetail_Item]
GO  
更新方法:

    public static void UpdateLicense(License license)
    {
        using (ALISEntities context = new ALISEntities())
        {
            context.ContextOptions.ProxyCreationEnabled = true;

            var storedLicense = 
                context.Licenses.Include("LicenseDetails")
                .Where(o => o.Id == license.Id).SingleOrDefault();

            //////////////////////////////////////////////////////////////
            // license details to add
            List<LicenseDetail> toAdd = new List<LicenseDetail>();

            foreach (LicenseDetail ld in license.LicenseDetails)
            {
                if (storedLicense.LicenseDetails
                    .Where(d => d.ItemId == ld.ItemId).Count() == 0)
                {
                    toAdd.Add(ld);
                }
            }

            toAdd.ForEach(i => storedLicense.LicenseDetails.Add(i));

            context.SaveChanges();
        }
    }
publicstaticvoidupdatelicense(许可证)
{
使用(ALISEntities上下文=新ALISEntities())
{
context.ContextOptions.ProxyCreationEnabled=true;
var storedLicense=
上下文。许可证。包括(“许可证详细信息”)
.Where(o=>o.Id==license.Id).SingleOrDefault();
//////////////////////////////////////////////////////////////
//要添加的许可证详细信息
List toAdd=新列表();
foreach(license.LicenseDetails中的LicenseDetail ld)
{
如果(storedLicense.LicenseDetails
.Where(d=>d.ItemId==ld.ItemId).Count()==0)
{
toAdd.Add(ld);
}
}
toAdd.ForEach(i=>storedLicense.LicenseDetails.Add(i));
SaveChanges();
}
}

将新的LicenseDetails添加到上下文中时,也会添加由这些LicenseDetails引用的项目。因为上下文不知道数据库中已经存在项,所以会添加它们。您需要通过调用context.Items.Attach(licenseDetail.Item)来告诉context数据库中已经存在项

您也可以尝试使用

context.Licenses.Include("LicenseDetails").Find(license.Id);
而不是

context.Licenses.Include("LicenseDetails")
                .Where(o => o.Id == license.Id).SingleOrDefault();

而且根本不需要使用添加列表-只需在第一个foreach循环中继续添加licenseDetails。

我最终不得不为添加的每个licenseDetails发出context.ObjectStateManager.ChangeObjectState(d.Item,EntityState.Unchanged)。这就解决了问题。

Jakub,非常感谢你的帮助。现在我明白了!谢谢你的额外提示@用户428774-不客气!我必须承认,这有点不直观,特别是当你来自一个不太“实体导向”的世界时,我昨天在家里回复你的回复,并将你的答案标记为接受答案,因为我相信你。然而,现在在办公室测试你的解决方案,我仍然有同样的问题。