Массовое редактирование MVC — сохранение списка Linq to Sql

Чтобы разобраться в некоторых основах использования MVC и Linq to SQL, я работаю над адаптацией к Приложение TaskList:

Я добавляю систему массового редактирования, используя концепции, описанные в блог Стива Сандерсона.

Все это работает, как и ожидалось, однако у меня возникли проблемы с сохранением возвращенного списка задач. Post to my BulkEdit перебирает возвращенный список и обновляет каждый элемент в моем списке задач LinqToSql db.

Мое представление BulkEdit наследует ViewPage<List<TaskList.Models.Task>> и выглядит следующим образом:

<% 
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" />

<%
    }
%>

Элемент управления TaskEditor наследует System.Web.Mvc.ViewUserControl<Models.Task> и выглядит следующим образом:

<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>

Методы получения и отправки контроллера следующие:

    [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");
    }

Мой вопрос в том, что это кажется слишком сложным, и я еще не учел задачи, добавляемые или удаляемые из списка. Я бы предпочел сделать что-то вроде

db.Tasks = tasks;

и пусть Linq делает всю свою магию, чтобы выяснить, какие из них изменились, а какие — новые/старые.

Это возможно? Или я так скоро ожидаю слишком многого от Linq?


person Robin Day    schedule 03.02.2009    source источник


Ответы (2)


Вы имеете дело с тем фактом, что LINQ to SQL не имеет многоуровневой истории. Я думаю, что это то, что вы ищете:

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

Метод Merge, который представляет этот парень, можно легко превратить в «метод расширения» класса DataContext, и он будет почти таким же, как если бы он был встроен прямо в LINQ to SQL. Я говорю «почти», потому что вам нужно будет указать пространство имен, в котором находится ваш метод расширения, чтобы использовать его.

person Wayne Bloss    schedule 04.02.2009

Я думаю, вам следует рассмотреть возможность использования представления для достижения того, чего вы хотите. коллекцию ObservebleCollection для хранения элементов, а затем вы можете иметь привязку в своем списке к представлению этой коллекции, вам все равно нужно будет обрабатывать случаи добавления и удаления элементов, но вы также можете выбрать IBindingList, который даст вам BindingListCollectionView, который будет обновлять БД, все, что вам нужно сделать, это вызвать представления AddNew(), CommitNew() и так далее.

ХТХ, Эрик

person user61477    schedule 03.02.2009