【问题标题】:MVC Entity Framework modifying child entitiesMVC 实体框架修改子实体
【发布时间】:2012-08-18 09:09:51
【问题描述】:

我对使用 MVC3 和 EF4 很陌生,我正在尝试实现父子实体集的 CRUD 功能,但是我还没有找到我需要的一些特定要求的示例,因此我想有点帮助。

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

通常这不是什么大问题,但在这种情况下,当用户将 Category 添加到 Product 时,我只需要允许用户能够从所有可用 @ 的列表中进行选择987654330@ 来自数据库。用户还可以从Product 中删除任何现有的子Categories

我希望使用所有未使用的“类别”来实现一个 DropDownList,但我不知道如何使用一个来允许用户添加和删除“类别”,然后通过以下方式将更改保存到数据库中英孚。

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

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

非常感谢。

【问题讨论】:

  • 你用的是什么类型的实体框架?代码优先、模型优先还是数据库优先?
  • 它的数据库优先。事实上,它是来自现有 winforms 产品的数据库,我试图从中复制一些网络上的功能。

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


【解决方案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; }
    }

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

【讨论】:

  • 非常感谢。今晚晚些时候我会试试这个。
  • 好吧,我刚才尝试实现这个,我遇到了几个问题,基本上没有显示与 PartialView 中的标签相关的内容。第一个警告出现在@if(ViewData["mode"]=="EDIT") 行,上面写着“期望常量”。我注意到的第二件事是在线 url: "/Author/SearchAuthor", type: "POST", dataType: "json",,我不知道那个 URL 是什么。你能帮我一下吗?谢谢。
  • @Alex,“SearchAuthor”方法根据用户的输入从数据库中搜索可用的作者。请参阅我更新的答案。关于@if(ViewData["mode"]=="EDIT"),你可以去掉'if'块并使else块无条件,然后在Edit.chtml视图中删除参数,如果它导致任何问题。
  • 感谢您的搜索方法,但它仍然无法正常工作:(。关于@if(ViewData["mode"]=="EDIT") 问题,这只是第一个警告,警告也显示在以下foreach 中。我查看 chrome javascript 控制台,我也收到两个错误:Uncaught TypeError: Object function (a,b){return new d.fn.init(a,b,g)} has no method 'widget' (tagit.js:10) 在 Edit.cshtml 文件中,Uncaught TypeError: Object [object Object] has no method 'tagit' (1:278 jquery-1.5.1.min.js:19) 在 AuthorsByBook 文件中。任何想法,因为我真的想让它工作!谢谢。
猜你喜欢
  • 1970-01-01
  • 2014-09-07
  • 1970-01-01
  • 2022-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多