Json column not updating through Controller

126 views Asked by At

I have a weird situation where my json column gets updated using unit test method but not though MVC controller.

Here is Test Method which updates the Phone Number and it's WORKING

public void Test_UpdateEmployee()
{
    Employee employee = employeeRepository.Get(emp => emp.Email == "[email protected]").Result.Single();

    employee.UpdatePhones(new List<StringValue> { "888" });
    employeeRepository.UpdateEmployeeAsync(employee);
}

And here is the Action in controller which does not send update to SQL server for Phone property

[HttpPost, ValidateAntiForgeryToken]
public async Task<IActionResult> Save(EditEmployeeViewModel model)
{
    model.Employee.UpdatePhones(new List<StringValue> { "888" });
    await _employeeRepository.UpdateEmployeeAsync(model.Employee);

    //All properties get updated, except Phones
    
    return RedirectToAction("Index");
}

Summary:

I checked through SQL Server Profiler and checked the Update statements, When using Test Method, Phone is included in update command, but saving the entity in controller action, does not included Phone property in update Command.

Note that the Action, updates all other properties like FirstName and LastName, but not updating Phone property which is a json column.

I can't figure out why it's not working in Action while Test Method is working correctly.

I will add more detail for Models and ViewModels if needed.

Update:

public async Task<IEnumerable<T>> Get(Expression<Func<T, bool>>? filter = null, Func<IQueryable<T>, IOrderedQueryable<T>>? orderBy = null, string includeProperties = "")
{
    IQueryable<T> query = dbSet;
    if (filter != null)
    {
        query = query.Where(filter);
    }

    foreach (var includeProp in includeProperties.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
    {
        query = query.Include(includeProp);
    }

    if (orderBy != null)
    {
        return await orderBy(query).ToListAsync();
    }

    return await query.ToListAsync();
}

public async Task UpdateEmployeeAsync(Employee employee)
{
    dbContext.Employees.Attach(employee);
    var entry = dbContext.Entry<Employee>(employee);
    entry.State = EntityState.Modified;
    await dbContext.SaveChangesAsync();
}

I also noticed if I fetch a new employee object instead of using the model.Employee, and assign the properties from model.Employee to it, it will work. Looks like something is wrong with the model.Emoloyee.

1

There are 1 answers

0
FLICKER On

I ended up with dirty solution. I had to save Employee and Phone in different phase.

[HttpPost, ValidateAntiForgeryToken]
public async Task<IActionResult> Save(EmployeeViewModel model)
{
    // Update Employee from model
    await _employeeRepository.UpdateEmployeeAsync(model.Employee);

    // Fetch Employee again from db, update Phones and update entity again.
    var inDb = await _employeeRepository.Get(emp => emp.Id == model.Employee.Id);
    var emp = inDb.Single();
    emp.UpdatePhones(model.Phones);
    _ = await _employeeRepository.UpdateEmployeeAsync(emp);

    return RedirectToAction("Index");
}

I could not save whole Employee in single save. Seems like a bug in EF Core?