为什么我的收藏集的更改不会持久存储到数据库中?

时间:2014-11-25 20:21:17

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

EnitityFramework在模型中处理带有Collection的多对多(*:*)。所以,我有一个SupportEventEmployee表,每个表都有(*:*)关系和集合。我需要在Razor页面上添加员工参加支持活动。

最初,我是通过在表单中​​单独传递数据而以不那么优雅的方式进行的。调用Edit(SupportEvent)方法时,对Employees集合所做的更改已存在。但是,当我调用SaveChanges(supportEvent)时,更改未持久保存到数据库。

环顾四周后,我发现ViewModel是正确处理这个问题的方法,所以我跟着MVC 5, Entity Framework 6 and Many to Many Relationship : a step by step View Model approach

即时问题"我发现,尽管这种方式可能更符合模式,但当我输入Edit()方法时,supportEvent完全相同,SaveChanges()的结果也是如此。除了名称和拼写错误之外,我无法以有意义的方式看到我的代码有所不同。

这是我的代码:

// 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; }
    }
}

编辑():

    // SupportEventController - Edit()
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Edit(SupportEventViewModel model, bool? active)
    {
        foreach(var e in model.SelectedEmployees) 
        {
            model.SupportEvent.Employees
                .Add(db.Employees.Find(e));
        }
        if (ModelState.IsValid)
        {
            db.Entry(model.SupportEvent).State = EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction(((bool)active) ? 
                "ActiveTicketDetails" : "Details", "Ticket", new { id = model.SupportEvent.TicketId });
        }
        return View(model);
    }

部分编辑视图:

// 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>

一切似乎都是正确的,我认为我在视图中所做的更改最终会在编辑方法中得到验证。我知道它没有被保存,因为当Edit重定向并且我返回到详细信息页面时,没有任何更改。

我遗漏/做错了什么阻止数据保存到数据库?

2 个答案:

答案 0 :(得分:0)

我认为这一行:

model.SupportEvent.Employees.Add(db.Employees.Find(e));

应替换为此行:

model.SupportEvent.Employees.Add(db.Employees.Find(emp => emp.Id = e));

因为 e 实际上是特定员工的 id (即选择(m =&gt; m.Id)的含义在SelectedEmployees上)

答案 1 :(得分:0)

我认为你所说的是员工可以有多个支持活动,支持活动可以有多个员工?如果没有中间的联结表,则无法映射此关系。您需要告诉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");
           }
}

现在添加或删除反之员工的事件非常容易。

var event = db.SupportEvents.FirstOrDefault(x => x.Id == "whatever");
var employee = db.Employee.FirstOrDefault(x => x.Id = "blah");
if(event == null || employee == null) return NotFound();

event.Employees.Add(employee);
// OR
employee.SupportEvents.Add(event);

db.SaveChanges();