[英]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.