这让我疯了。我不知道还有什么可以尝试的。这是我最近尝试使用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块。
接下来,我需要弄清楚如何删除一个或多个项目,但首先要先删除...
答案 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);
}
}