Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC Bulk Edit - Linq to Sql List Save

To get my head round some fundamentals using MVC and Linq to SQL I'm working on an adaption to Stephen Walther's TaskList application:

I'm adding a Bulk Edit system using the concepts described in Steve Sanderson's blog.

This all works as expected, however, I'm having trouble saving my returned List of Tasks. The Post to my BulkEdit loops through the returned list and updates each item in my LinqToSql db list of Tasks.

My BulkEdit view inherits ViewPage<List<TaskList.Models.Task>> and is as follows:

<% 
using (Html.BeginForm())
{
%>
        <div id="items">

<%
            foreach (var task in ViewData.Model)
            {
                Html.RenderPartial(
                    "TaskEditor",
                    task,
                    new ViewDataDictionary(ViewData)
                            {
                                {"prefix", "tasks"}
                            }
                );
            }
%>

        </div>

        <input type="submit" value="Save changes" />

<%
    }
%>

The TaskEditor control inherits System.Web.Mvc.ViewUserControl<Models.Task> and looks like this:

<div>
<%= Html.Hidden(ViewData["prefix"] + ".index", ViewData.Model.Id) %>

<% var fieldPrefix = string.Format("{0}[{1}].", ViewData["prefix"], ViewData.Model.Id); %>

<%= Html.Hidden(fieldPrefix + "Id", ViewData.Model.Id) %>
Description:
<%= Html.TextBox(fieldPrefix + "TaskDescription", ViewData.Model.TaskDescription)%>
Date:
<%= Html.TextBox(fieldPrefix + "EntryDate", ViewData.Model.EntryDate.ToString("o"))%>   
Completed:
<%= Html.CheckBox(fieldPrefix + "IsCompleted", ViewData.Model.IsCompleted)%>
</div>

The Controller Get and Post methods are as follows:

    [AcceptVerbs(HttpVerbs.Get)]
    public ActionResult BulkEdit()
    {
        var tasks = from t in db.Tasks orderby t.EntryDate descending select t;

        return View(tasks.ToList());
    }        

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult BulkEdit(IList<Task> tasks)
    {
        foreach(Task task in tasks)
        {
            foreach(Task dbTask in db.Tasks)
            {
                if (dbTask.Id == task.Id)
                {
                    dbTask.TaskDescription = task.TaskDescription;
                    dbTask.EntryDate = task.EntryDate;
                    dbTask.IsCompleted = task.IsCompleted;
                }
            }
        }

        db.SubmitChanges();

        return RedirectToAction("Index");
    }

My question is, this seems too complicated and I haven't yet accounted for tasks being added or deleted from the list. What I would prefer to do is something like

db.Tasks = tasks;

and let Linq do all its magic to work out which ones have changed and which ones are new / old.

Is this possible? Or am I expecting a bit too much from Linq so soon?

like image 861
Robin Day Avatar asked Feb 03 '09 08:02

Robin Day


1 Answers

You're dealing with the fact that LINQ to SQL has no multi-tier story. I think that this is what you're looking for:

http://blog.irm.se/blogs/eric/archive/2008/08/20/Go-Distributed-With-LINQ-to-SQL.aspx

The Merge method that this guy presents could be easily turned into an "extension method" of the DataContext class and it would almost be just like it was built right into LINQ to SQL. I say almost because you'd have to include the namespace of where your extension method is located in order to use it.

like image 154
Wayne Bloss Avatar answered Sep 27 '22 18:09

Wayne Bloss