使用Entity Framework更新数据库,比较方法

时间:2016-07-08 21:42:46

标签: asp.net-mvc entity-framework

我认为这些方法本质上是相同的,但第一个方法首先查询数据库,因此由于击中数据库两次而导致性能降低。我最多只有40个用户,所以性能不是太大的问题。有没有其他理由使用其中一个?

首先从数据库中抓取实体,更改它然后保存它:

    public void UpdateStudent(StudentModel model)
    {
        using (var _db = new AppEntities())
        {
            Student student = new Student();

            student = _db.Student.Find(model.studentId);

            student.FirstName = model.FirstName;
            student.LastName = model.LastName;
            student.DOB = model.DOB;
            student.GradeId = model.GradeId;

            _db.Entry(student).State = System.Data.Entity.EntityState.Modified;
            _db.SaveChanges();
        }
    }

更改实体,让EF在数据库中找到它并更新:

    public void UpdateStudent(StudentModel model)
    {
        using (var _db = new AppEntities())
        {
            Student student = new Student()
            {
                student.StudentId = model.StudentId,
                student.FirstName = model.FirstName,
                student.LastName = model.LastName,
                student.DOB = model.DOB,
                student.GradeId = model.GradeId
            };

            _db.Entry(student).State = System.Data.Entity.EntityState.Modified;
            _db.SaveChanges();
        }
    }

2 个答案:

答案 0 :(得分:1)

在第一个代码段中,您将获取某个版本的实体表单db。如果其他线程或进程修改了同一个实体,我不认为EF会让你只是进行更新,因为你的基本版本的实体与更新查询之前的数据库中的实体不同。

在第二个中,如果某个线程或进程在您处理此请求时修改了该实体,则可能会丢失该更改。

编辑:我从不厌倦。我总是得到实体,然后修改并保存,但你可以写一个测试来验证发生了什么。

答案 1 :(得分:1)

在您的第一个代码段中,您不必将实体标记为Modified,因为更改跟踪器会处理此问题。这一点很重要,因为它还定义了两种方法之间的差异。我会解释一下。

让我们假设所有作业(student.FirstName = model.FirstName;等)只有第一个是真正的改变。如果是的话 -

  • 第一个代码片段(但未将实体标记为Modified)会触发更新FirstName的更新语句。
  • 第二个代码片段始终更新Student所有字段。

这意味着第一个片段不太可能导致并发冲突(其他人可能会同时更改LastName并且您不会通过陈旧数据覆盖此修改,如第二个场景中所发生的那样)。

所以它涉及细粒度的变化与全面的更新,往返与冗余:

  • 第一个场景需要进行往返,但更加安全可靠。
  • 第二种情况不需要往返,但并发安全性较低。

由您来平衡权衡取舍。

为了让这个选择更加困难,还有第三个选择:

public void UpdateStudent(StudentModel model)
{
    using (var _db = new AppEntities())
    {
        Student student = new Student()
        {
            student.StudentId = model.StudentId,
            student.FirstName = model.FirstName,
            student.LastName = model.LastName,
            student.DOB = model.DOB,
            student.GradeId = model.GradeId
        };
        _db.Students.Attach(student);

        _db.Entry(student).Property(s => s.FirstName).IsModified = true;
        _db.Entry(student).Property(s => s.LastName).IsModified = true;
        _db.Entry(student).Property(s => s.DOB).IsModified = true;
        _db.Entry(student).Property(s => s.GradeId).IsModified = true;
        _db.SaveChanges();
    }
}

没有往返,现在您只将4个属性标记为已修改。因此,如果实际只更改了一个属性,您仍然会更新太多属性,但是四个属性比所有属性更好。

此外还有更多" rondtrips vs redundancy"问题,但我解释了elswhere