使用外键编辑/创建EF对象

时间:2011-01-10 05:05:15

标签: c# asp.net-mvc entity-framework model-binding

我对使用ASP.NET MVC和Entity Framework时处理外键关系的最佳方法感兴趣。

我目前正在使用ViewModel来输出创建和编辑页面(使用部分),但是当我将数据发回时,情况不会很好。

在验证我的模型之前,我使用选择列表中的发布值来查找外来对象并将其分配给我的模型,但是当我在编辑时使用UpdateModel时,引用最终为null,I我猜是因为它无法正确绑定该属性。

人们通常如何处理这个问题?使用ViewModel填充我的下拉列表似乎足够困难,但在编辑时我必须遗漏一些东西。人们通常会创建自己的活页夹来解决这个问题吗?

我尝试过使用强类型和FormCollection

ViewModel:

public class ReportViewModel
 {
    public Report Report { get; set; }
    public SelectList ReportDeliveryMethods { get; set; }
    public string ReportDeliveryMethod { get; set; }
    public SelectList ReportReceivers { get; set; }
    public string ReportReceiver { get; set; }
    public SelectList PermitTypes { get; set; }
    public string PermitType { get; set; }
}

控制器:

[HttpPost]        
public ActionResult Edit(int id, FormCollection collection)
        {
            Report report;

            try
            {
                report = repository.GetReport(id);

                // Convert ReportDeliveryMethod to Object Reference                        
                if (!string.IsNullOrEmpty(collection["ReportDeliveryMethod"]))
                {
                    int reportDeliveryMethodId = 0;
                    if (int.TryParse(collection["ReportDeliveryMethod"], out reportDeliveryMethodId))
                    {
                        report.ReportDeliveryMethod = repository.GetReportDeliveryMethod(reportDeliveryMethodId);
                    }
                }

                // Convert ReportReceiver to Object Reference              
                if (!string.IsNullOrEmpty(collection["ReportReceiver"]))
                {
                    int reportReceiverId = 0;
                    if (int.TryParse(collection["ReportReceiver"], out reportReceiverId))
                    {
                        report.ReportReceiver = repository.GetReportReceiver(reportReceiverId);
                    }
                }

                // Convert PermitType to Object Reference              
                if (!string.IsNullOrEmpty(collection["PermitType"]))
                {
                    int permitTypeId = 0;
                    if (int.TryParse(collection["PermitType"], out permitTypeId))
                    {
                        report.PermitType = repository.GetPermitType(permitTypeId);
                    }
                }

                if (ModelState.IsValid)
                {
                    UpdateModel(report);
                    repository.Save();

                    return RedirectToAction("Index");
                }
                else
                {
                    return View();
                }
            }
            catch (Exception ex)
            {
                return View();
            }
        }

形式:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<PermitLookup.Models.ReportViewModel>" %>
<% using (Html.BeginForm())
   {%>
<%: Html.ValidationSummary(true) %>
<fieldset>
    <legend>Fields</legend>
    <div class="editor-label">
        <%: Html.LabelFor(model => model.Report.ShareName) %>
    </div>
    <div class="editor-field">
        <%: Html.TextBoxFor(model => model.Report.ShareName) %>
        <%: Html.ValidationMessageFor(model => model.Report.ShareName)%>
    </div>
    <div class="editor-label">
        <%: Html.LabelFor(model => model.Report.Description) %>
    </div>
    <div class="editor-field">
        <%: Html.TextBoxFor(model => model.Report.Description)%>
        <%: Html.ValidationMessageFor(model => model.Report.Description)%>
    </div>
    <div class="editor-label">
        <%: Html.LabelFor(model => model.Report.Frequency)%>
    </div>
    <div class="editor-field">
        <%: Html.TextBoxFor(model => model.Report.Frequency)%>
        <%: Html.ValidationMessageFor(model => model.Report.Frequency)%>
    </div>
    <div class="editor-label">
        <%: Html.LabelFor(model => model.Report.SendTime)%>
    </div>
    <div class="editor-field">
        <%: Html.TextBoxFor(model => model.Report.SendTime)%>
        <%: Html.ValidationMessageFor(model => model.Report.SendTime)%>
    </div>
    <div class="editor-label">
        <%: Html.LabelFor(model => model.Report.ReportDeliveryMethod)%>
    </div>
    <div class="editor-field">
        <%=Html.DropDownListFor(model => model.ReportDeliveryMethod, Model.ReportDeliveryMethods)%>
        <%: Html.ValidationMessageFor(model => model.Report.ReportDeliveryMethod)%>
    </div>
    <div class="editor-label">
        <%: Html.LabelFor(model => model.Report.ReportReceiver)%>
    </div>
    <div class="editor-field">
        <%=Html.DropDownListFor(model => model.ReportReceiver, Model.ReportReceivers)%>
        <%: Html.ValidationMessageFor(model => model.Report.ReportReceiver)%>
    </div>
    <div class="editor-label">
        <%: Html.LabelFor(model => model.Report.PermitType)%>
    </div>
    <div class="editor-field">
        <%=Html.DropDownListFor(model => model.PermitType, Model.PermitTypes)%>
        <%: Html.ValidationMessageFor(model => model.Report.PermitType)%>
    </div>
    <p>
        <input type="submit" value="Save" />
    </p>
</fieldset>
<% } %>

1 个答案:

答案 0 :(得分:1)

让我们考虑一下ReportDeliveryMethod。在您的视图模型中,它是string。在Report对象上,它是ReportDeliveryMethod类型。由于string无法隐式转换为ReportDeliveryMethod,因此UpdateModel不会绑定它。

那你有什么选择?

  1. 手动映射,就像你现在正在做的那样。
  2. 绑定ID,而不是对象引用。 EF 4支持FK associations。您可以将ReportDeliveryMethodId放在视图模型中,而不是ReportDeliveryMethod