使用EF 4.3更新子集合 - 在DB中丢失关联

时间:2012-05-30 01:56:08

标签: c# entity-framework

这让我疯了。我不知道还有什么可以尝试的。这是我最近尝试使用EF 4.3更新另一个对象中的对象列表。

方案是用户已将新任务添加到已在其Tasks属性中具有一个任务的应用程序。应用程序未附加到DB上下文,因为它是在先前的逻辑/数据库调用中检索的。这是类和属性:

public class Application : EntityBase
{
    public ObservableCollection<TaskBase> Tasks { // typical get/set code here }
}

这是我尝试更新列表。发生的事情是添加新任务并且DB中正确存在关联。但是,第一个未被更改的任务在DB中删除了它的关联(它对应用程序的引用)。

这是采用用户修改的应用程序的Save()方法:

public void Save(Application newApp)
{
    Application appFromContext;

    appFromContext = this.Database.Applications
        .Include(x => x.Tasks)
        .Single(x => x.IdForEf == newApp.IdForEf);

    AddTasksToApp(newApp, appFromContext);
    this.Database.SaveChanges();
}

这是使用EF保存显然需要的风险:

private void AddTasksToApp(Application appNotAssociatedWithContext, Application appFromContext)
{
    List<TaskBase> originalTasks = appFromContext.Tasks.ToList();

    appFromContext.Tasks.Clear();

    foreach (TaskBase taskModified in appNotAssociatedWithContext.Tasks)
    {
        if (taskModified.IdForEf == 0)
        {
            appFromContext.Tasks.Add(taskModified);
        }
        else
        {
            TaskBase taskBase = originalTasks.Single(x => x.IdForEf == taskModified.IdForEf);  // Get original task
            this.Database.Entry(taskBase).CurrentValues.SetValues(taskModified);  // Update with new
        }
    }
}

任何人都可以看到为什么第一个任务会失去与DB中的应用程序的关联?第一个任务是通过上面代码中的else块。

接下来,我需要弄清楚如何删除一个或多个项目,但首先要先删除...

1 个答案:

答案 0 :(得分:0)

经过不断的反复试验,这似乎有效,包括删除任务。我以为我会发布这个,以防它帮助其他人。我也希望有人告诉我,我正在使它变得比它应该更复杂。保存具有list属性的每个对象时,这是一个繁琐且容易出错的代码。

private void AddTasksToApp(Application appNotAssociatedWithContext, Application appFromContext)
{
    foreach (TaskBase taskModified in appNotAssociatedWithContext.Tasks)
    {
        if (taskModified.IdForEf == 0)
        {
            appFromContext.Tasks.Add(taskModified);
        }
        else
        {
            TaskBase taskBase = appFromContext.Tasks.Single(x => x.IdForEf == taskModified.IdForEf);  // Get original task
            this.Database.Entry(taskBase).CurrentValues.SetValues(taskModified);  // Update with new
        }
    }

    // Delete tasks that no longer exist within the app.
    List<TaskBase> tasksToDelete = new List<TaskBase>();
    foreach (TaskBase originalTask in appFromContext.Tasks)
    {
        TaskBase task = appNotAssociatedWithContext.Tasks.Where(x => x.IdForEf == originalTask.IdForEf).FirstOrDefault();

        if (task == null)
        {                    
            tasksToDelete.Add(originalTask);
        }
    }

    foreach (TaskBase taskToDelete in tasksToDelete)
    {                
        appFromContext.Tasks.Remove(taskToDelete);
        this.Database.TaskBases.Remove(taskToDelete);
    }
}