如何使用实体框架保存带有外键的新记录

本文关键字:新记录 何使用 实体 框架 保存 | 更新日期: 2023-09-27 18:35:23

所以我有两个模型,产品和评论。产品模型包含一个名为"审阅"的导航属性,如下所示:

Public class Product
{
    [HiddenInput(DisplayValue=False])
    public int ProductID {get; set;}
    [Required]
    public string ProductName {get; set;}
    [HiddenInput(DisplayValue=False)
    public ICollection<Reviews> {get; set;}
}

审查模型:

public class Review
{
    [HiddenInput(DisplayValue=false)]
    public int ReviewId { get; set; }
    [Required]
    public int ProductID { get; set; }
    [Required]
    public string Name { get; set; }
    [Required]
    public string Subject { get; set; }
    [Required]
    public string Body { get; set; }
}

我有一个Action ViewResult方法,用于产品详细信息,它可以获取所有产品以及具有相同FK产品ID的所有评论,如下所示:

public ViewResult ProductDetails(int productId)
{
    Product product = repository.Products
        .Include(p => p.Reviews)
        .FirstOrDefault(p => p.ProductID == productId);
    return View(product);
}

然后有一个包含非常简单的HTML元素的View,您可以在下面看到它:

@model app.models.Product
@Html.DisplayFor(model => model.ProductName)
@foreach (var review in Model.Reviews)
{
    @Html.Partial("_Reviews", review)
}

在上面的视图中,我要求使用部分视图来呈现所有评论都属于该特定产品。在"部分"视图中,我有一个表单,用户可以在其中提交评论。我希望用户提交名称位于视图顶部的产品的评论。我知道我必须为此创建一个操作,但唯一让我感到不舒服的是我无法弄清楚如何获得该特定产品的ProductID

编辑:根据斯蒂芬的回答,我不得不将表单 Html 元素放入主视图中,即 ProducDetails,并放置了一些脚本来调用 Json 结果以将数据保存在数据库中。

保存审阅的控制器方法:

[HttpPost]
        public JsonResult CreateReview (Review review)
        {
            if (review.ReviewId == 0)
            {
                db.Reviews.Add(review);
            }
            else
            {
                Review dbEntry = db.Reviews.Find(review.ReviewId);
                if (dbEntry != null)
                {
                    dbEntry.ProductID = review.ProductID;
                    dbEntry.Name = review.Name;
                    dbEntry.Subject = review.Subject;
                    dbEntry.Body = review.Body;
                }
            }
            db.SaveChanges();
            return Json(true);
        }

如何使用实体框架保存带有外键的新记录

您希望

Product创建一个新Review,因此窗体需要位于主视图中,而不是部分视图中。以下假设您希望使用 ajax 提交并更新现有评论的列表

@model app.models.Product
@Html.DisplayFor(model => model.ProductName)
// display existing reviews
<div id="reviews">
    @foreach (var review in Model.Reviews)
    {
        @Html.DisplayFor(m => review.Body)
    }
</div>
<h2>Create new Review</h2>
@Html.Partial("_NewReview", new Review(){ ProductID = Model.ProductID })

_NewReview.cshtml在哪里

@model Review
@using (Html.BeginForm())
{
    @Html.HiddenFor(m => m.ProductID)
    @Html.EditorFor(m => m.Name)
    @Html.EditorFor(m => m.Subject)
    @Html.TextAreaFor(m => m.Body)
    <input id="create" type="submit" value="Create" />
}

并删除_Reviews.cshtml文件

然后在主视图中,添加以下脚本

var url = '@Url.Action("Create", "Review")';
var reviews = $('#reviews');
var form = $('form');
$('#create').click(function() {
    $.post(url, form.serialize(), function(response) {
        if (response) {
            reviews.append($('#Body').val()); // add the new Review to the existing reviews
            form.get(0).reset(); // reset the form controls
        }
    }).fail(function (result) {
        // oops
    });
    return false; // cancel the default submit
});

将提交给(ReviewController

[HttpPost]
public JsonResult Create(Review model)
{
    // Save the model
    return Json(true); // return something to indicate success
}

正如我所能想象的那样,ProductId 是唯一的在分部视图中,您可以在 Ajax.BeginForm 中编写代码

@model Review
@Ajax.BeginForm("ActionName", "ControllerName", new { productId = Model.ProductId }, @*AjaxOptions Attribute*@)
{
     Review Fields here
     <input type="submit" value="Submit Review"/>
}

要获得ProductID,您必须在Review Table中添加Product TableForeignKey

public class Review
{
    [HiddenInput(DisplayValue=false)]
    public int ReviewId { get; set; }
    [Required]
    public int ProductID { get; set; }
    [Required]
    [ForeignKey("ProductID")]
    publiv virtual Product {get;set;}
}

希望这有帮助