1

Я оглядывался и не мог найти ответ. Я использую ViewModel в своем Редактировании вида, чтобы иметь значения для какого-либо выпадающего списка. Теперь, когда я иду обновлять свою БД, я не понимаю, как я могу обновить свою запись в базе данных. Я предполагаю, что я мог бы создать новый объект сущности, сделать Find, а затем обновить каждое свойство на основе ViewModel, переданного из формы, но это, несомненно, похоже на большую ручную работу.Обновить объект с помощью ViewModel и Entity Framework 6?

Здесь я использую VeiwModel в Edit View.

@model CPPCustomerCall.ViewModels.CustomerCallVM 

Вот мой отзыв о действии ControlResult. Я изменил тип объекта ActionResult, чтобы использовать CustomerCallVM вместо ClientCall, который был автоматически сгенерирован. Я предполагаю, что поскольку модель Edit View является ViewModel, это тип объекта, который получит ActionResult. Однако у моего ViewModel больше свойств, которые не нужны для модели Entity для обновления записи. Как мне перейти на обновление моей записи БД в этом ActionResult?

[HttpPost] 
[ValidateAntiForgeryToken] 
public async Task<ActionResult> Edit([Bind(Include = "Id,CustomerName,Subject,PhoneNumber,CallMessage,CallDate,Status,CallNotes")] CustomerCallVM customerCall) 
{ 
    if (ModelState.IsValid) 
    { 
     db.Entry(customerCall).State = EntityState.Modified; 
     await db.SaveChangesAsync(); 
     return RedirectToAction("Index"); 
    } 
    return View(customerCall); 
} 

ответ

4

Во-первых, Bind и вид модели являются взаимоисключающими. Если вы не хотите, чтобы что-то имело право на изменение, тогда оно не должно быть на вашей модели просмотра, в первую очередь. Если учесть, что модели просмотра отклоняются от объектов в том смысле, что они не могут быть сохранены напрямую. В результате всегда есть какое-то вмешательство с вашей стороны, чтобы отобразить опубликованные значения обратно в объект, что означает, что вы можете выборочно не отображать определенные свойства, которые не должны быть, независимо от того, были ли они опубликованы или нет. Длинные и короткие, избавьтесь от вещей Bind. Это просто что-то еще для поддержания и огромный источник потенциальных ошибок.

При этом код, который у вас есть, работоспособен; вам просто не хватает ключевой части, где вы сопоставляете данные с вашей модели представления обратно на свою сущность. Во-первых, вам нужно получить объект из базы данных, так у вас есть база для работы с:

var customerCall = db.CustomerCalls.Find(id); 
if (customerCall == null) 
{ 
    return new HttpNotFoundResult(); 
} 

FWIW, ваши изменения маршрута должны включать идентификатор в маршруте, в соответствии с конвенциями REST. После REST строго не требуется, но это, безусловно, рекомендуется. В то время как веб-приложение, придерживающееся REST, не означает, что это хорошее приложение, не, придерживаясь отдыха, как правило, является верным признаком плохо разработанного и закодированного приложения.

Затем вы переводите свои объекты. Вы можете сделать это вручную:

customerCall.CustomerName = model.CustomerName; 
// etc. 

Или вы можете использовать библиотеку как AutoMapper.

mapper.Map(model, customerCall); 

AutoMapper требует немного первоначальной настройки, чтобы сделать эту волшебную работу, конечно, поэтому проверьте документацию, если вы собираетесь этот маршрут. Ручное сопоставление проще, но гораздо более утомительно и повторяемо.

+0

Спасибо. Материал Bind был сгенерирован автоматически, и я помню, как читал некоторые уроки из Channel9. Я верю, что они предложили использовать его, чтобы не допустить публикации. В любом случае, у меня нет проблем, потому что это похоже на дополнительную работу, которая, по крайней мере, для этого сценария, вероятно, слишком велика. Что касается другого кода, это звучит так, как будто мне нужно создать новый объект сущности и отобразить свойства из переданного ViewModel. Я решил, что это один из способов справиться с этим, но просто казался потенциальным дополнительным кодом. Однажды я посмотрел AutoMapper, но также прочитал, чтобы держаться подальше от него. – Caverman

+1

Будьте осторожны с тем, что вы читаете. Там много плохой информации.AutoMapper просто отлично, если вы используете его правильно. Проблема возникает как с чем угодно, когда вы начинаете чрезмерно полагаться на нее. Материал «Bind» - это попытка Microsoft извинить за то, что она жалеет дизайн. Истина заключается в том, что сущность - это * не * модель, и нет смысла использовать один и тот же класс для публикации данных, как вы используете для сохранения данных. В течение многих лет Microsoft продолжала настаивать на этой плохой практике, быстро используя «Bind», чтобы замаскировать огромную проблему безопасности. –

0
[HttpPost] 
[ValidateAntiForgeryToken] 
public async Task<ActionResult> Edit([Bind(Include = "Id,CustomerName,Subject,PhoneNumber,CallMessage,CallDate,Status,CallNotes")] CustomerCallVM customerCall) 
{ 
    if (ModelState.IsValid) 
    { 
     // Find The record you need 
     var dbObj = CustomerCalls.FirstOrDefault(x=> x.id = customerCall.id); 
     //Check if null 
     if(dbObj == null) dbObj = new CustomerCall(); 

     /// Map your properties 

     // Add object to the stack 
     if(dbObj.id == 0){ 
     CustomerCalls.Add(dbObj); 
     }else{ 
     CustomerCalls.Update(dbObj); 
     } 

    await db.SaveChangesAsync(); 
    return RedirectToAction("Index"); 
    } 
    return View(customerCall); 
} 
Смежные вопросы