EF 4 - POCO - SaveChanges意外地重复查找表中的项目

时间:2010-10-28 21:56:06

标签: entity-framework-4 poco

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

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

数据库中定义的两个表(SQLServer 2008)的关系如下所示,我首先执行数据库,因此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();
        }
    }

2 个答案:

答案 0 :(得分:0)

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

您也可以尝试使用

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

而不是

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

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

答案 1 :(得分:0)

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