MVC实体框架修改子实体

时间:2012-08-22 21:29:00

标签: asp.net-mvc-3 entity-framework

我对使用MVC3和EF4以及尝试实现父子实体集的CRUD功能都很陌生,但我还没有找到一些具体要求的示例我需要,因此需要一些帮助。

我的情况是我有一个Product实体,它有一个子Category个实体。我让所有CRUD功能都适用于Product实体以及在Category详细信息视图中使用Product实体的详细功能。但是,我需要从给定的Categories中添加和删除子Product

通常这不是一个大问题,但在这种情况下,当用户向Category添加Product时,我只需要允许用户从中进行选择数据库中所有可用Categories的列表。用户还可以从Categories中移除任何现有的子Product

我希望使用所有未使用的'类别'来实现DropDownList。会很好,但我不知道如何使用一个允许用户添加和删除'类别'然后通过EF将更改保存到数据库。

有没有人有任何关于如何完成此事的建议/示例?

如果需要任何额外信息,请询问。

非常感谢。

1 个答案:

答案 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());
            }
        }