Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detect state change of model property, in controller, using Entity Framework

I have a more or less standard looking model:

public class Project {
  public int ID { get; set; }
  //... some more properties

  public DateTime StartDate { get; set; }
  public int Duration { get; set; }
}

If the user modifies StartDate or project Duration, I have to call a function to update a simulation. In order to achieve this I'd like to detect the state change of the fields StartDate and Duration within a controller.

Something like that:

if(project.StartDate.stateChange() || project.Duration.stateChange())

Here is an example of what the Controller Method would look like:

[HttpPost]
public ActionResult Edit(Project project)
{
    if (ModelState.IsValid)
    {
        if(project.StartDate.stateChange() || project.Duration.stateChange())
            doSomething();

        db.Entry(project).State = EntityState.Modified;
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(project);
}

Any idea, how can I achieve this?

like image 831
Chopo87 Avatar asked May 22 '13 09:05

Chopo87


People also ask

How to track changes in Entity Framework by the context?

To track any entity by the context, it must have the primary key property. In Entity Framework, change tracking is enabled by default. You can also disable change tracking by setting the AutoDetectChangesEnabled property of DbContext to false. If this property is set to true then the Entity Framework maintains the state of entities.

What is each entity state in Entity Framework 6?

Each entity has a state based on the operation performed on it via the context class. The entity state represented by an enum System.Data.Entity.EntityState in EF 6 and Microsoft.EntityFrameworkCore.EntityState in EF Core with the following values: The Context not only holds the reference to all the entity objects as soon as retrieved from ...

What does the detached entity state indicate in Entity Framework?

The Detached entity state indicates that the DbContext is not tracking the entity. Entity Framework Core Attach method allows us to attach an Detached entity to context and start tracking it. In the following code, we are attaching two entities ( Department1 & Department2 ).

How to change the state of an entity that is already tracked?

You can change the state of an entity that is already being tracked by setting the State property on its entry. For example: Note that calling Add or Attach for an entity that is already tracked can also be used to change the entity state.


Video Answer


2 Answers

I believe you can compare the edited entity with the original one read from the database.

Something like:

public ActionResult Edit(Project project)
{
    if (ModelState.IsValid)
    {
        var original = db.Find(project.ID);
        bool changed = original.StartDate != project.StartDate || original.Duration != project.Duration;
        if (changed)
        {
            original.StartDate = project.StartDate;
            original.Duration = project.Duration;
            doSomething();
            db.Entry(original).CurrentValues.SetValues(project);
            db.SaveChanges();
        }
    }
    return View(project);
}
like image 105
Stefan Szasz Avatar answered Nov 21 '22 21:11

Stefan Szasz


You can solve it by carrying old values via ViewBag.

In action:

public ActionResult Edit(int? id)
{
    //...Your Code
    ViewBag.OrigStartDate = project.StartDate;
    ViewBag.OrigDuration = project.Duration;
    return View(project);
}

Add hidden elements to View

...
@Html.Hidden("OrigStartDate", (DateTime)ViewBag.OrigStartDate)
@Html.Hidden("OrigDuration", (int)ViewBag.OrigDuration)
...

Add these parameters to the post method and check them for changes

[HttpPost]
public ActionResult Edit(DateTime OrigStartDate, int OrigDuration)
{
    if (ModelState.IsValid)
    {
        if (OrigStartDate != project.StartDate || OrigDuration != project.Duration)
            doSomething();

        db.Entry(project).State = EntityState.Modified;
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    ViewBag.FileTypeId = new SelectList(db.FileTypes, "Id", "TypeName", dbinfo.FileTypeId);
    return View(project);
}
like image 25
OrcaYlc Avatar answered Nov 21 '22 21:11

OrcaYlc