簡體   English   中英

使用MVC 4和Entity Framework更新相關數據嗎?

[英]Updating related data using MVC 4 and Entity Framework?

因此,我在保存包含相關實體的數據時遇到了問題,當我將其保存時會創建一個新的關系空白。

例:

實體:

public class Project
{
    public int Id { get; set; }
    public int Code{ get; set; }
    public string Description{ get; set; }

    public virtual Client Client { get; set; }
}


public class Client
{
    public int Id { get; set; }
    public int Code { get; set; }
    public string Name { get; set; }
}

控制器GET:

public ActionResult Create()
{
    PopulateDropDownClienteList(String.Empty); //Returns to ViewBag to create a combobox .in view
    return View();
}

風景:

 @Html.DropDownListFor(m => m.Client.Id, new SelectList(ViewBag.Client_Id, "Id", "Name"), new { Name = "Client.Id" });

控制器POST:

[HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create(string command, Project project)
    {
        try
        {
            if (ModelState.IsValid)
            {
                projectRepository = new ProjeRepository();
                Project pro = projectRepository.ReturnByCode(project.Code);

                if (pro == null)
                    projectRepository.Save(project);
                else
                    projectRepository.Update(project);

                PopulateDropDownClienteList(String.Empty);

                Return View();

            }
            else
            {
                return View(project);
            }
        }
        catch (Exception ex)
        {
            return View();
        }
    }

因此,當我保存數據時,客戶端未與項目關聯。 只是創建一個新的空白客戶端。

您在這里遇到了很多問題,所以讓我分解一下。

首先, 永遠不要捕獲Exception (至少不要再次拋出它)。 使用try...catch塊有兩個非常重要的事情:您只應將代碼包裝在您期望發生異常的位置(而不是您在此處所做的幾乎整個方法),並且只應捕獲特定的異常期待(不是基本類型Exception )。 當您捕獲Exception ,將捕獲可能從您的代碼生成的所有異常,並且在這種情況下,將其簡單地丟棄,這意味着您真的將永遠不知道此代碼是否可以正常工作。

其次,您可以使用一種很好的方法來生成選項的下拉列表,但不要將用戶的選擇存儲在有意義的位置。 要了解原因,您需要停下來思考一下這里發生的事情。 HTML select元素具有字符串值和字符串文本或標簽組件。 它不支持來回傳遞完整對象。 我看不到您的PopulateDropDownClienteList方法做什么,但是它應該做的是創建一個IEnumerable<SelectListItem> ,其中每個項目的Text屬性設置為想要顯示的內容,而Value屬性設置為Client PK。 但是,一旦有了它,就需要在Project上添加一些屬性以回發到該屬性。 您的虛擬Client無法使用,因為它需要一個完整的Client實例,而您的表單將永遠不會有該實例。 因此,您有兩種選擇:

  1. 實現視圖模型以饋送到視圖(並在帖子中接受)。 在該視圖模型中,除了所有其他可編輯字段外,還將包括ClientId類的類型,它將是一個int類型,並將其綁定到下拉列表中。 使用post方法后,將所有發布的值映射到您的項目實例,然后使用ClientId從數據庫中查找客戶端。 然后,將結果客戶設置為Client屬性的值,並照常保存。

  2. 您會稍微更改數據庫。 當您只指定一個虛擬時,Entity Framework會巧妙地創建一個外鍵和一列以在后台為您保留該關系。 太好了,但是在這種情況下,實際上您需要訪問該外鍵列,這很麻煩。 解決該問題的方法是顯式定義一個屬性以在模型上保留該關系,並告訴Entity Framework使用該屬性,而不是創建自己的屬性。

     [ForeignKey("Client")] public int ClientId { get; set; } public virtual Client Client { get; set; } 

    這樣,您現在可以直接使用ClientId而不必擔心填寫Client 您再次將下拉列表綁定到ClientId ,但是現在,您無需從數據庫中顯式查找客戶端。 Entity Framework只會將ClientId正確保存到數據庫中,然后在以后再次查找項目時基於該Client ClientId還原Client

您的項目保存代碼不是在更新實體,而是一直在添加新的實體。

您應該具有與以下理由類似的更新邏輯-

要添加新的FK條目並將其與父記錄相關聯-

var entity = entities.Students.Where(p => p.Id == "2").First();
entity.StudentContact = new StudentContact() { Contact = "xyz", Id = "2" };

entities.Students.Attach(entity);
var entry = entities.Entry(entity);
// other changed properties
entities.SaveChanges();

要使用新的詳細信息更新FK記錄-

var entity = entities.Students.FirstOrDefault();
entity.StudentContact.Contact = "ABC";

entities.Students.Attach(entity);
var entry = entities.Entry(entity);
entry.Property(e => e.StudentContact.Contact).IsModified = true;
// other changed properties
entities.SaveChanges();

上面的代碼,我有一個Student記錄,它與StudentContacts有FK關系。 我更新了學生的聯系信息,然后使用ATTACH將其更新到數據庫。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM