[英]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
實例,而您的表單將永遠不會有該實例。 因此,您有兩種選擇:
實現視圖模型以饋送到視圖(並在帖子中接受)。 在該視圖模型中,除了所有其他可編輯字段外,還將包括ClientId
類的類型,它將是一個int
類型,並將其綁定到下拉列表中。 使用post方法后,將所有發布的值映射到您的項目實例,然后使用ClientId
從數據庫中查找客戶端。 然后,將結果客戶設置為Client
屬性的值,並照常保存。
您會稍微更改數據庫。 當您只指定一個虛擬時,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.