MVC Entity Framework модифицирует дочерние объекты
Я довольно новичок в использовании MVC3 и EF4, и я пытаюсь реализовать функции CRUD набора родительских и дочерних объектов, однако я не нашел пример некоторых конкретных требований, которые мне нужны, и поэтому я хотел бы немного Помогите.
Ситуация у меня такова, что у меня есть Product
сущность, которая имеет ребенка Category
юридические лица. У меня все функции CRUD работают нормально для Product
сущность и функциональность деталей, работающих с Category
сущность в пределах Product
подробный вид. Однако мне нужно осуществить добавление и удаление ребенка Categories
из данного Product
,
Обычно это не будет большой проблемой, но в этом случае, когда пользователь добавляет Category
к Product
Мне нужно только позволить пользователю иметь возможность выбирать из списка всех доступных Categories
из базы данных. Пользователь также сможет удалить любого существующего потомка Categories
из Product
,
Я ожидаю, что реализация DropDownList со всеми неиспользованными "категориями" будет работать хорошо, однако я не знаю, как использовать один, чтобы позволить пользователю добавлять и удалять "категории", а затем сохранять изменения в базе данных через EF.
Кто-нибудь получил какие-либо предложения / примеры, как это сделать?
Если требуется дополнительная информация, пожалуйста, спросите.
Спасибо большое.
1 ответ
Я сделал то же самое с авторами и книгами, связанными многими со многими. Основная идея состоит в том, чтобы создать объект JSON из представления, в котором содержатся все авторы, и передать его в контроллер. Я также использовал jQuery UI TagIt, чтобы позволить пользователю добавлять / удалять авторов, связанных с книгой. Когда пользователь нажимает кнопку "Сохранить книгу", сценарий создает объект JSON, который имитирует объект "Книга".
Ниже приведен код. Пожалуйста, убедитесь, что вы добавили "json2.js" и "tagit.js" в проект, прежде чем пытаться использовать этот код.
Посмотреть модели:
public class BookViewModel
{
public string Title { get; set; }
public int BookId { get; set; }
public int IsAvail { get; set; }
public string CallNumber { get; set; }
//Assiged authors
public List<AuthorViewModel> Authors { get; set; }
//available authors
public List<AuthorViewModel> AuthorOptions { get; set; }
}
public class AuthorViewModel
{
public int AuthorId { get; set; }
public string FirstName { get; set; }
}
Код для книги /Edit.chtml:
@using System.Web.Script.Serialization
@model eLibrary.Models.BookViewModel
@{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
@*This is for JSON*@
<script src="../../Scripts/json2.js" type="text/javascript"></script>
<script src="../../Scripts/tagit.js" type="text/javascript"></script>
@*These are for styling Control*@
<link href="../../Content/themes/base/jquery.ui.all.css" rel="stylesheet" type="text/css" />
<script type="text/javascript">
//This function is used for sending data(JSON Data) to BookController
function BookSave() {
// Step 1: Read View Data and Create JSON Object
var author = { "AuthorId": "", "FirstName": "" };
// Creating book Json Object
var book = { "BookId": "", "Title": "", "IsAvail": "", "CallNumber":"", "authors": []};
// Set Boook Value
book.BookId = $("#BookId").val();
book.Title = $("#Title").val();
book.IsAvail = $("#IsAvail").val();
book.CallNumber = $("#CallNumber").val() ;
var tags = $('#authors').tagit('tags');
for (var i in tags) {
author.AuthorId = tags[i].value;
author.FirstName = tags[i].label;
book.authors.push(author );
author = { "AuthorId": "", "FirstName": "" };
}
// Step 1: Ends Here
// Set 2: Ajax Post
// Here i have used ajax post for saving/updating information
$.ajax({
url: '/Book/Edit',
data: JSON.stringify(book),
type: 'POST',
contentType: 'application/json;',
dataType: 'json',
success: function (result) {
if (result.Success == "1") {
window.location.href = "/Book/Edit";
}
else {
alert(result.ex);
}
}
});
}
</script>
@using (Html.BeginForm())
{
@Html.ValidationSummary(true)
<fieldset>
<legend>Book Details</legend>
@Html.HiddenFor(model => model.BookId)
<div class="editor-label">
@Html.LabelFor(model => model.Title)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Title)
@Html.ValidationMessageFor(model => model.Title)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.IsAvail)
</div>
@Html.EditorFor(model => model.IsAvail)
@Html.ValidationMessageFor(model => model.IsAvail)
@Html.EditorFor(model => model.CallNumber);
</fieldset>
@Html.Partial("AuthorsByBook", Model.Authors, new ViewDataDictionary { { "mode", "EDIT" } })
<input type="button" value="Book Save" onclick="BookSave()" />
}
Код для Книги /AuthorsByBook.chtml
@model IEnumerable< eLibrary.Models.AuthorViewModel>
<link href="../../Content/tagit-awesome-blue.css" rel="stylesheet" type="text/css" />
<div class="box">
<ul id="authors" name="authors">
</ul>
</div>
<script type="text/javascript">
//Load authors in the javascript variable
$(function () {
var initialAuthorList=[];
@if(ViewData["mode"]=="EDIT")
{
foreach (var category in Model)
{
<text>
initialAuthorList.push({label: "@category.FirstName", value: @category.AuthorId });
</text>
}
}
$('#authors').tagit({tagSource: function (request, response) {
$.ajax({
url: "/Author/SearchAuthor", type: "POST", dataType: "json",
data: { searchText: request.term, maxResults: 10 },
success: function (data) {
response($.map(data, function (item) {
return { label: item.FirstName, value: item.AuthorId }
}))
}
})
},
initialTags:initialAuthorList,minLength:3,allowNewTags:false,sortable:true,delay:400});
});
</script>
Код для BookController.cs
public ActionResult Edit(int id)
{
//To DO: use repository to fetch data
Book book = db.Books.Single(a => a.BookId == id);
Mapper.CreateMap<Book, BookViewModel>();
Mapper.CreateMap<Author, AuthorViewModel>();
BookViewModel bookVm = Mapper.Map<Book, BookViewModel>(book);
List<AuthorViewModel> Authors = Mapper.Map<List<Author>,List<AuthorViewModel>>( db.Authors.ToList());
bookVm.AuthorOptions = Authors;
return View(bookVm);
}
[HttpPost]
public ActionResult Edit(BookViewModel bookv)
{
//create maps
Mapper.CreateMap<AuthorViewModel, Author>();
Mapper.CreateMap<BookViewModel, Book>();
//convert view objects to model objects
Book book = Mapper.Map<BookViewModel, Book>(bookv);
List<Author> authors = Mapper.Map<List<AuthorViewModel>, List<Author>>(bookv.Authors.ToList());
//this has to be executed before db.Books.Attach
//clear authors
book.Authors.Clear();
db.Books.Attach(book);
//assign authors to book
foreach (Author a in authors) { db.Authors.Attach(a); }
book.Authors.Clear();
foreach (Author a in authors) { book.Authors.Add(a); }
db.ObjectStateManager.ChangeObjectState(book, EntityState.Modified);
db.SaveChanges();
return RedirectToAction("Index");
}
Код для метода SearchAuthor в AuthorController.cs
public JsonResult SearchAuthor(string searchText, int? maxResults)
{
IEnumerable<Author> query = db.Authors;
searchText = searchText.ToLower();
query = query.Where(c => c.FirstName.ToLower().Contains(searchText));
if ((maxResults ?? 0) == 0)
{
return Json(query.ToList());
}
else
{
return Json(query.Take((int)maxResults).ToList());
}
}