我对使用MVC3和EF4以及尝试实现父子实体集的CRUD功能都很陌生,但我还没有找到一些具体要求的示例我需要,因此需要一些帮助。
我的情况是我有一个Product
实体,它有一个子Category
个实体。我让所有CRUD功能都适用于Product
实体以及在Category
详细信息视图中使用Product
实体的详细功能。但是,我需要从给定的Categories
中添加和删除子Product
。
通常这不是一个大问题,但在这种情况下,当用户向Category
添加Product
时,我只需要允许用户从中进行选择数据库中所有可用Categories
的列表。用户还可以从Categories
中移除任何现有的子Product
。
我希望使用所有未使用的'类别'来实现DropDownList。会很好,但我不知道如何使用一个允许用户添加和删除'类别'然后通过EF将更改保存到数据库。
有没有人有任何关于如何完成此事的建议/示例?
如果需要任何额外信息,请询问。
非常感谢。
答案 0 :(得分:0)
我与作者和书籍的作用类似,具有多对多的关系。基本思想是从视图创建一个JSON对象,其中包含其中的所有作者并提交给控制器。我还使用了jQuery UI TagIt来允许用户添加/删除与该书相关联的作者。当用户单击“保存书籍”按钮时,该脚本会构建一个模仿Book对象的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; }
}
Book / 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()" />
}
Book / 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");
}
AuthorController.cs中的SearchAuthor方法代码
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());
}
}