C# 为什么对我的集合所做的更改不保留到数据库中?
EntityFramework使用模型中的集合处理多对多*:*。因此,我有一个SupportEvent和Employee表,每个表中都有*:*关系和集合。我需要将员工添加到Razor页面上的支持活动中 最初,我是以一种不那么优雅的方式通过表单分别传递数据来完成的。调用EditSupportEvent方法时,将显示对Employees集合所做的更改。但是,当我调用SaveChangessupportEvent时,更改并没有持久化到数据库中 环顾四周后,我发现ViewModels是正确处理此问题的方法,因此我遵循了 我发现的直接问题是,尽管这种方式可能更符合模式,但当我输入Edit方法时,supportEvent完全相同,SaveChanges的结果也一样。撇开名字和打字错误不谈,我看不到我的代码有任何有意义的不同之处 这是我的密码:C# 为什么对我的集合所做的更改不保留到数据库中?,c#,asp.net-mvc,entity-framework,C#,Asp.net Mvc,Entity Framework,EntityFramework使用模型中的集合处理多对多*:*。因此,我有一个SupportEvent和Employee表,每个表中都有*:*关系和集合。我需要将员工添加到Razor页面上的支持活动中 最初,我是以一种不那么优雅的方式通过表单分别传递数据来完成的。调用EditSupportEvent方法时,将显示对Employees集合所做的更改。但是,当我调用SaveChangessupportEvent时,更改并没有持久化到数据库中 环顾四周后,我发现ViewModels是正确处理此问题的方
// ViewModel
public class SupportEventViewModel
{
public SupportEvent SupportEvent { get; set; }
public IEnumerable<SelectListItem> AllEmployees { get; set; }
private List<int> selectedEmployees;
public List<int> SelectedEmployees
{
get
{
if (selectedEmployees == null)
{
selectedEmployees = SupportEvent
.Employees
.Select(m => m.Id)
.ToList();
}
return selectedEmployees;
}
set { selectedEmployees = value; }
}
}
和部分编辑视图:
// The partial view/form
@model ProjectWhiteWave.ViewModels.SupportEventViewModel
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title></title>
</head>
<body>
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>SupportEvent</h4>
<hr />
@Html.ValidationSummary(true)
@Html.HiddenFor(model => model.SupportEvent.SupportEventId)
<div class="form-group">
@Html.LabelFor(model => model.SupportEvent.DateOpened, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.SupportEvent.DateOpened)
@Html.ValidationMessageFor(model => model.SupportEvent.DateOpened)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.SupportEvent.DateClosed, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.SupportEvent.DateClosed)
@Html.ValidationMessageFor(model => model.SupportEvent.DateClosed)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.AllEmployees, "Technicians", new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.ListBoxFor(model => model.SelectedEmployees, Model.AllEmployees)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.SupportEvent.Description, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.SupportEvent.Description)
@Html.ValidationMessageFor(model => model.SupportEvent.Description)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
</body>
</html>
一切似乎都是正确的,我认为我在视图中所做的更改最终会在编辑方法中得到验证。我知道它没有被保存,因为当编辑重定向和我返回到详细信息页面时,没有出现任何更改
我遗漏了什么/做错了什么,阻止了数据保存到数据库?我认为这行:
model.SupportEvent.Employees.Add(db.Employees.Find(e));
model.SupportEvent.Employees.Add(db.Employees.Find(emp => emp.Id = e));
应替换为以下行:
model.SupportEvent.Employees.Add(db.Employees.Find(e));
model.SupportEvent.Employees.Add(db.Employees.Find(emp => emp.Id = e));
因为e实际上是一个特定员工的id,这就是Selectm=>m的意思。在SelectedEmployees上的id我想你是说一个员工可以有多个支持活动,支持活动可以有多个员工?如果没有中间的连接表,就无法映射这种关系。您需要告诉EF基于此关系创建一个连接表 如果您已经这样做了,那么只需忽略前面的语句,但请查看下面的代码,了解我如何设置简单的多对多关系,以及这是否有帮助
public class Employee
{
[Key]
public Guid Id { get; set; }
public virtual ICollection<SupportEvent> SupportEvents { get; set; }
}
public class SupportEvent
{
[key]
public Guid Id { get; set; }
public virtual ICollection<Employee> Employees { get; set; }
}
// DbContext
public DbSet<Employee> Employees { get; set; }
public DbSet<SupportEvent> SupportEvents { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Employee>()
.HasMany(x => x.SupportEvents)
.WithMany(x => x.Employees)
.Map(m =>
{
m.ToTable("EmployeeSupportEvents");
m.MapLeftKey("EmployeeId");
m.MapRightKey("SupportEventId");
}
}
那似乎不行。虽然它是Id,但find是基于该Id查找的。当调用Save时,employees已经添加到本地实例中,ModelState是有效的,但是没有写入任何内容。因此,我在寻找解决方案时看到了这种方法。我首先用模型开始这个项目;当我在模型生成器中设置断点运行项目时,没有一个断点被命中。你知道调用它的方法吗?如果那样会破坏我的工作流程。你如何将DbContext注入到你的控制器中?它应该在实例化时调用此方法。在我的例子中,控制器实例是通过Unity DI创建的。是否确保每次调用都使用新实例?控制器是自动生成的。在控制器内部,它创建一个db上下文。这不是应该的方式?我将一个视图模型从上面的表单传递到控制器中。是的,但它正在创建一个新模型,对吗?它没有引用静态实例或单例?我现在会删除自动生成的一个,并在操作中创建它,以查看它是否被正确创建。然后尝试读取一些现有数据,这将让您知道您的上下文是否正常或至少具有读取权限。然后尝试添加一个实体并保存,然后检查您的关系。我想我需要花一些时间来更改。它很快就会抱怨使用新的db上下文引用了一个IEntityTracker的多个实例。这两种方式都还没有被称为,我认为这方面的任何改变都不重要。在方法中,在添加更改之前,它包含抛出新的UnnotedDefirstException。我想我会找到解决方法,然后反过来做。谢谢