views:

57

answers:

4

Is there an easier way to update an object with L2S other then doing it property by property?

This is what I am doing now:

Public ActionResult Edit(Object obj)
{
    var objToUpdate = _repository.Single<Object>(o => o.id = obj.id);
    objToUpdate.Prop1 = obj.Prob1;
    objToUpdate.Prop2 = obj.Prop2;

    ...

    _repository.SubmitChanges();
}

I am hoping there is a way to just say objToUpdate = obj then submit the changes???

Any help on this would be appreciated!

A: 

You are doing it right. You need to have a DataContext to actually do the update and MVC will not be able to create that for you. However, there are plenty of things you could do to reduce the code in the controller so it seems much more simple. This is what we do at my job. We have templated methods to take care of things in a much cleaner way.

John
+1  A: 

I think what you're wanting is explained in this blog. It is easier than the model copying or property mapping stuff that is out there if what you're truly working with is perfectly represented by your L2S result object.

Jaxidian
+1  A: 

I've used a slightly more complicated variation of the following pattern:

protected ActionResult Update<T>(Expression<Func<T, bool>> predicate, Action<IDataContext, T> action, params string[] whitelist) where T : class
{
  using (var context = ContextFactory.GetContext())
  {
    try
    {

      var model = context.GetTable<T>().Where(predicate).SingleOrDefault();

      if (model == null) throw new ApplicationException("Item not found");

      if (whitelist != null && whitelist.Length > 0)
      {
        TryUpdateModel(model, whitelist);
      }
      else
      {
        TryUpdateModel(model);
      }

      if (action != null) action(context, model);

      context.SubmitChanges();

      return Success();

    }
    catch (SqlException ex)
    {
      return HandleSqlException(ex);
    }
    catch (Exception ex)
    {
      return Failure();
    }

  }
}

This allows you to write a basic Update action as simple as:

public ActionResult Update(int id)
{
  return Update<Customer>(c => c.CustomerID == id);
}

This uses a different overload of the above code, where the Action<,> isn't passed in, which is used to allow you to inject custom binding code if TryUpdateModel does not suffice. For example:

public ActionResult Update(int id)
{
  return Update<Customer>
  (
    c => c.CustomerID == id,
    (context, c) => 
    {
      c.LastModified = DateTime.Now;
    }
  );
}

It's not flexible enough for all update cases, but probably suffices for most dumb CRUD scenarios. You can use this to centralize your exception handling, logging, mapping of difficult kinds of properties (mainly booleans, because checkboxes are not posted in HTML if they're unchecked, but also nullable value types).

JulianR