如果使用EF

时间:2018-02-23 16:57:45

标签: entity-framework entity-framework-6

当我使用Entity Framework 6(首次使用EF)构建项目时,我注意到当我 Update Entity,EF的关系时也会更新主Entity

我可以说这种情况正在发生,因为我在System Versioned上使用了Sql Server 2017个表格。

这是一个弥补的场景,但大部分概念都在这里。

public async Task<ActionResult> Edit([Bind(Include="Id,Name,LocationTimes")] LocationViewModel locationVM) {
    if (ModelState.IsValid) {
        var location = await _db.Locations.FirstOrDefaultAsync(l => l.Id == locationsViewModel.Id && l.UserId == UserId);
        if (location == null) {
            return HttpNotFound();
        }

        location.Name = locationsViewModel.Name;
        // ... other properties

        foreach (var day in locationsViewModel.LocationTimes.Days) {
            var time = new Time {
                Day = day.Day,
                OpenTime = day.OpenTime,
                CloseTime = day.CloseTime,
            };

            // Find current Time or keep newly created
            time = await time.FindByTimeAsync(time, _db) ?? time;

            // Find LocationTime with same day
            var locationTime = location.LocationTimes.FirstOrDefault(lt => lt.Time.Day == day.Day);

            // If all times are the same, skip (continue)
            if (locationTime != null && locationTime.Time.OpenTime == time.OpenTime && locationTime.Time.CloseTime == time.CloseTime)
                continue;

            if (locationTime != null && (locationTime.Time.OpenTime != time.OpenTime || locationTime.Time.CloseTime != time.CloseTime)) {
                // Remove, At least one of the Times do not match
                locationTime.Time = time;
                _db.Entry(locationTime).State = EntityState.Modified;
            } else {
                location.LocationTimes.Add(new LocationTime {
                    Location = location,
                    Time = time,
                });
            }
        }

        _db.Entry(location).State = EntityState.Modified;
        await _db.SaveChangesAsync();
        return RedirectToAction("Index");
    }
}

我假设,通过将整个Entity标记为Modified,EF将调用更新语句。

如果父作案中没有UPDATE发生更改,我仍然可以避免向Entityproperties Add发送Update / location孩子的关系?

我假设我必须检查每个属性是否都没有更改,因此我不应该将Modified状态设置为Times,但是如何处理新添加的public async Task<ActionResult> Edit([Bind(Include="Id,Name,LocationTimes")] LocationViewModel locationVM) { if (ModelState.IsValid) { var location = await _db.Locations.FirstOrDefaultAsync(l => l.Id == locationsViewModel.Id && l.UserId == UserId); if (location == null) { return HttpNotFound(); } /******************* This is new part *******************/ if ( location.Name != locationsViewModel.Name // || ... test other properties ) { location.Name = locationsViewModel.Name; // ... other properties _db.Entry(location).State = EntityState.Modified; } else { _db.Entry(location).State = EntityState.Unchanged; } /*******************/ foreach (var day in locationsViewModel.LocationTimes.Days) { var time = new Time { Day = day.Day, OpenTime = day.OpenTime, CloseTime = day.CloseTime, }; // Find current Time or keep newly created time = await time.FindByTimeAsync(time, _db) ?? time; // Find LocationTime with same day var locationTime = location.LocationTimes.FirstOrDefault(lt => lt.Time.Day == day.Day); // If all times are the same, skip (continue) if (locationTime != null && locationTime.Time.OpenTime == time.OpenTime && locationTime.Time.CloseTime == time.CloseTime) continue; if (locationTime != null && (locationTime.Time.OpenTime != time.OpenTime || locationTime.Time.CloseTime != time.CloseTime)) { // Remove, At least one of the Times do not match locationTime.Time = time; _db.Entry(locationTime).State = EntityState.Modified; } else { location.LocationTimes.Add(new LocationTime { Location = location, Time = time, }); } } /* removed, added above */ //_db.Entry(location).State = EntityState.Modified; await _db.SaveChangesAsync(); return RedirectToAction("Index"); } } ?< / p>

更新#1

所以我尝试了我提到的并且它有效,这是正确的方法吗?

* def foo = 5
* assert foo <= 6

* def bar = { a: 1 }
* match bar == { a: '#? _ > 0' }

1 个答案:

答案 0 :(得分:0)

因此,经过反复试验,我想我误解了EF如何处理EntityState。我虽然childModified,但您必须将父级设为Modified

很高兴,情况并非如此,下面的代码可以正常工作。

public async Task<ActionResult> Edit([Bind(Include="Id,Name,LocationTimes")] LocationViewModel locationVM) {
    if (ModelState.IsValid) {
        var location = await _db.Locations.FirstOrDefaultAsync(l => l.Id == locationsViewModel.Id && l.UserId == UserId);
        if (location == null) {
            return HttpNotFound();
        }

        /*******************
        This is new part

        check if at least one property was changed
        *******************/
        if (
            location.Name != locationsViewModel.Name
            || location.Ref != locationsViewModel.Ref
        //  || ... test other properties
        ) {
            location.Name = locationsViewModel.Name;
            location.Ref = locationsViewModel.Ref;
            // ... other properties

            // Tell EF that the Entity has been modified (probably not needed, but just in case)
            _db.Entry(location).State = EntityState.Modified;
        } else {
            // Tell EF that the Entity has *NOT* been modified
            _db.Entry(location).State = EntityState.Unchanged;
        }
        /*******************/

        foreach (var day in locationsViewModel.LocationTimes.Days) {
            var time = new Time {
                Day = day.Day,
                OpenTime = day.OpenTime,
                CloseTime = day.CloseTime,
            };

            // Find current Time or keep newly created
            time = await time.FindByTimeAsync(time, _db) ?? time;

            // Find LocationTime with same day
            var locationTime = location.LocationTimes.FirstOrDefault(lt => lt.Time.Day == day.Day);

            // If all times are the same, skip (continue)
            if (locationTime != null && locationTime.Time.OpenTime == time.OpenTime && locationTime.Time.CloseTime == time.CloseTime)
                continue;

            if (locationTime != null && (locationTime.Time.OpenTime != time.OpenTime || locationTime.Time.CloseTime != time.CloseTime)) {
                // Remove, At least one of the Times do not match
                locationTime.Time = time;
                _db.Entry(locationTime).State = EntityState.Modified;
            } else {
                location.LocationTimes.Add(new LocationTime {
                    Location = location,
                    Time = time,
                });
            }
        }

        /* removed, added above */
        //_db.Entry(location).State = EntityState.Modified;
        await _db.SaveChangesAsync();
        return RedirectToAction("Index");
    }
}