5

在同时修改和添加子行时,我遇到了一些麻烦。我正在使用答案中的技术:stackoverflow.com/questions/5557829/ ...。

问题出在以下代码中:

public void EditReport(tbl_inspection inspection)
{
    foreach (var roll in inspection.tbl_inspection_roll)
    {                    
        container.tbl_inspection_roll.Attach(roll);
        container.ObjectStateManager.ChangeObjectState(roll, (roll.id_inspection_roll == 0) ? EntityState.Added : EntityState.Modified);
    }

    container.SaveChanges();
}

我总是至少有 1 行要更新。当我要添加 1 行时,它工作正常,问题是当我尝试同时添加多于 1 行时,显示众所周知的错误:

ObjectStateManager 中已存在具有相同键的对象。ObjectStateManager 无法跟踪具有相同键的多个对象。

感觉好像我在这里错过了一些东西......

4

3 回答 3

1

我认为您需要将修改后的内容与添加的内容分开。在您链接到 Ladislav 的问题中,有以下代码作为示例:

if (myEntity.Id != 0)
{
    context.MyEntities.Attach(myEntity);
    context.ObjectStateManager.ChangeObjectState(myEntity, EntityState.Modified);
}
else
{
    context.MyEntities.AddObject(myEntity);
}

context.SaveChanges();

我认为专门使用 Attach 而不是使用 AddObject 是导致错误的原因。

编辑:请尝试以下附加部分:

var r = new tbl_inspection_roll { id_inspection_roll = roll.id_inspection_roll };
container.tbl_inspection_roll.Attach(r);
container.Entry(r).CurrentValues.SetValues(roll);
于 2013-01-03T15:23:10.563 回答
1

这里的问题是因为两个或多个子存根具有相同的键:0。一旦您尝试附加第一个对象,它就会触发错误。

必须使用某种 DTO 重新设计该方法(我认为将 ViewModel 对象传递给域模型层是不正确的,这就是我使用存根的原因)。或者直接从控制器调用一个函数来添加/修改。

编辑:

这是代码:

public void EditReport(Inspection obj)
{
    var inspection = new tbl_inspection
    {
        id_inspection = obj.ID,
        code = obj.Code       
    };

    foreach (var roll in obj.Rolls)
    {                    
        var rollStub = new tbl_inspection_roll
        {
            id_inspection_roll = roll.ID,
            id_inspection = obj.ID,
            description = roll.Description
        };

        container.tbl_inspection_roll.Attach(roll);
        container.ObjectStateManager.ChangeObjectState(roll, (roll.id_inspection_roll == 0) ? EntityState.Added : EntityState.Modified);
    }

    container.tbl_inspection.Attach(inspection);
    container.ObjectStateManager.ChangeObjectState(inspection, EntityState.Modified);

    container.SaveChanges();
}

欢迎任何更好的解决方案......

于 2013-01-04T13:34:41.727 回答
0

如果我正确理解您的问题,您正在尝试保存包含 ParentObject 和相关 ChildObjects 的对象图并且您收到异常,因为 Attach() 无法协调数据库中 ChildObjects 和附加 ParentObject 之间的 Id 冲突。

以下是我过去使用过的解决方法。它不漂亮,但它完成了工作。

public ParentObject Upsert(ParentObject newParentObject)
{
    // Check for an existing ParentObject.
    ParentObject exisitingParentObject = container.ParentObjects.SingleOrDefault(o => o.Id == newParentObject.Id);

    // If not an existing ParentObject
    if (exisitingParentObject == null)
    {
        // Add a new ParentObject
        exisitingParentObject = container.ParentObjects.Add(container.ParentObjects.Create());
    }

    // Update the properties of the existing ParentObject with the values of the new ParentObject
    var parentEntry = container.Entry(exisitingParentObject);
    parentEntry.CurrentValues.SetValues(newParentObject);

    // Remove ChildObjects that are in the existing but not in the new.
    for (int i = exisitingParentObject.ChildObjects.Count() - 1; i >= 0; i--)
    {
        ChildObject exisitingChildObject = exisitingParentObject.ChildObjects[i];
        if (!newParentObject.ChildObjects.Any(o => o.Id == exisitingChildObject.Id))
        {
            container.ChildObjects.Remove(exisitingChildObject);
        }
    }

    // Upsert new ChildObjects
    foreach (ChildObject newChildObject in newParentObject.ChildObjects)
    {
        // Check for an existing ChildObject
        ChildObject exisitingChildObject = exisitingParentObject.SingleOrDefault(o => o.Id == newChildObject.Id);

        // If not an existing ChildObject
        if (exisitingChildObject == null)
        {
            // Add a new ChildObject
            exisitingChildObject = exisitingParentObject.ChildObjects.Add(container.ChildObject.Create());
        }

        var childEntry = container.Entry(exisitingChildObject);
        childEntry.CurrentValues.SetValues(newChildObject);
    }

    container.SaveChanges();

    return exisitingParentObject;
}
于 2013-01-03T20:21:27.293 回答