C# 使用枚举更新实体时不首先删除ef代码中的旧条目

C# 使用枚举更新实体时不首先删除ef代码中的旧条目,c#,asp.net-mvc,entity-framework,C#,Asp.net Mvc,Entity Framework,我有一个教师实体,它没有正确更新我的“瑜伽课堂”表,它正在向“瑜伽课堂”写入新值,但没有删除/修改旧值。要解决此问题,我需要重新构造控制器以修改旧值,还是需要在插入新值之前修改存储库以删除旧值 public class Teacher { // other members... public virtual ICollection<YogaClass> YogaClasses { get; set; } } 这里是YogaStyle enum public enum

我有一个教师实体,它没有正确更新我的“瑜伽课堂”表,它正在向“瑜伽课堂”写入新值,但没有删除/修改旧值。要解决此问题,我需要重新构造控制器以修改旧值,还是需要在插入新值之前修改存储库以删除旧值

public class Teacher
{
   // other members...
   public virtual ICollection<YogaClass> YogaClasses { get; set; } 
}
这里是YogaStyle enum

public enum YogaStyle
{
    [Display(Name = "Beginner Anusara")]
    BeginnerAnusara,
    [Display(Name = "Intermediate Anusara")]
    IntermediateAnusara,
    // more members here...
}
如果老师已经添加了瑜珈课(多选下拉列表),它将如下所示

现在让我们假设老师进入并取消选择她以前的一些选择,并添加新的选择。当我更新时,实体框架不会删除/删除/修改以前的条目,它只会像这样写入新条目。您可以看到老师删除了1,4,6并添加了52,53,54,55

在我的控制器中,在我的存储库中“UpdateOrInsert()”之前,我只是在这里设置老师选择的所有类

 public ActionResult Edit(EditTeacherViewModel viewModel)
 {  
     // other code here...
     teacher.YogaClasses = GetSelectedClasses(viewModel);
     teacherRepository.InsertOrUpdate(teacher);
 }
下面是GetSelectedClasses方法

 private ICollection<YogaClass> GetSelectedClasses(EditTeacherViewModel viewModel)
    {
        ICollection<YogaClass> classes = new Collection<YogaClass>();
        int[] selectedClasses = viewModel.SelectedYogaStyles;
        foreach (int selectedClass in selectedClasses)
        {
            YogaClass yogaClass = new YogaClass();
            yogaClass.YogaStyle = (YogaStyle)selectedClass;
            classes.Add(yogaClass);
        }
        return classes;
    }

您需要将旧条目设置为EntityState.Deleted。我会在服务器端更加明确,例如有一个delete-ActionResult。这也应该更易于测试。您还想删除YogaClass实体,因此您可能需要一个控制器来执行此操作?没有理由您不能从教师操作结果的更新/插入中调用此

更新回复问题: 您需要删除YogaClass记录,而不是教师记录。例如:

var teacher = new Teacher();
teacher.id = 0;
teacher.Yogaclasses = new List<YogaClass>();
context.Teachers.Add(teacher);
context.SaveChanges
保存更改等

当您从数据库中检索Id为1的教师时,详细信息都保存到数据库中后,上下文将为您填充瑜伽课堂。假设你做了10次瑜伽课,他们的ID是1到10

如果我随后将此列表提供给客户端,并且当我将教师对象接收回我的更新方法时,客户端会删除Id为1和2的YogaClass,那么我可以:

从上下文中检索当前数据库对象(列表中仍有10个YogaClass项); 我可以在context ObjText中迭代YogaClass项,并检查ViewModel对象是否具有相同的记录。对于ViewModel上不存在但上下文对象上确实存在的任何项目,需要删除它们

我知道我有两个YogaClass条目(id 1和2)需要删除。这是一个单独的问题(始终思考固体!!)。我可以在我的存储库中公开DeleteYogaClass(YogaClass YogaClass)方法或DeleteYogaClass(IEnumerable YogaClass)

对于单个酸奶组:

    try
    {
        context.YogaClasses.Remove(yogaClass);
        context.SaveChanges();
    }
    catch (OptimisticConcurrencyException ex)
    {
        throw new InvalidOperationException(string.Format(
            "The YogaClass with an ID of '{0}' could not be deleted etc etc";
    }

对于一个以上的类foreach并将all设置为deleted。

说得好@Luthervd,在发布更新的条目之前,首先清除旧条目。

在将其从数据库中删除之前,“旧”条目需要处于“deleted”状态。替换集合并不能做到这一点。这是否意味着我应该在执行“InsertOrUpdate()”之前删除repo中的teacher对象?您找到这个问题的答案了吗?我今天要面对它(你能提供一点更详细的信息吗?我应该在哪里设置?存储库的InsertOrUpdate方法还是我应该先删除教师对象。我有点不确定这应该发生在哪里。请查看我的更新答案。我认为你误解了如何管理上下文对象的状态。我在这里看到的问题是我传递给客户端的e列表中没有来自yogaclass对象的id。我传递的是MultiSelectList(样式、“id”、“名称”、selectedValues);其中ID是枚举索引,Name是枚举的名称。因此,我不会将YogaClassId传递到客户端模型对象中。我应该是吗?我可以吗?我可以在另一个重载的MultSelectList中传递它吗?这是另一个问题,但您可以-有人说永远不会在客户端上传递实体的ID-在这样做时考虑安全性。看看你的YogaClass对象。如果老师不能复制此列,你的瑜伽风格可能是一个唯一的约束。你可以使用此列和老师Id来查找记录。如果不是,则Id是唯一的标识符,你应该使用此-或向表中添加唯一标识符元素。正如我所说,这是一个不同的问题,但要删除数据库中的记录您需要能够找到它和主键。我尝试将“context.Entry(teacher.YogaClasses).State=EntityState.Deleted;”添加到我的repo中的UpdateOrInsert()中,但这引发了一个错误。
var teacher = new Teacher();
teacher.id = 0;
teacher.Yogaclasses = new List<YogaClass>();
context.Teachers.Add(teacher);
context.SaveChanges
var yogaClass = new YogaClass();
yogaClass.yogastyle = 1;
yogaClass.teacherId = 1: 
    try
    {
        context.YogaClasses.Remove(yogaClass);
        context.SaveChanges();
    }
    catch (OptimisticConcurrencyException ex)
    {
        throw new InvalidOperationException(string.Format(
            "The YogaClass with an ID of '{0}' could not be deleted etc etc";
    }