一个表

时间:2015-11-27 01:06:32

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

我对3个表之间的关系有一些问题。所有这些之间存在多对多的关系 - 我的模型类如下所示:

public partial class Bus
{
    public Bus()
    {
        this.Lines = new HashSet<Line>();
        this.Drivers = new HashSet<Driver>();
    }

    public int BusID { get; set; }
    public string RegNum { get; set; }
    [StringLength(3)]
    public string Status { get; set; }

    public virtual ICollection<Line> Lines { get; set; }
    public virtual ICollection<Driver> Drivers { get; set; }
}

    public partial class Driver
{
    public Driver()
    {
        this.Buses = new HashSet<Bus>();
    }

    public int DriverID { get; set; }
    public string DriverName { get; set; }
    public string DriverSurname { get; set; }
    [StringLength(3)]
    public string Status { get; set; }

    [Display(Name = "Driver")]
    public string DriverInfo
    {
        get
        {
            return DriverName + " " + DriverSurname;
        }
    }

    public virtual ICollection<Bus> Buses { get; set; }
}


public partial class Line
{
    public Line()
    {
        this.Schedules = new HashSet<Schedule>();
        this.Buses = new HashSet<Bus>();
    }

    public int LineID { get; set; }
    public int LineNumber { get; set; }
    public string Direction { get; set; }

    [Display(Name = "Line: Direction")]
    public string LineInfo
    {
        get
        {
            return LineNumber + ": " + Direction;
        }
    }

    public virtual ICollection<Bus> Buses { get; set; }
}

的DbContext:

public partial class ModelEntities : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        throw new UnintentionalCodeFirstException();
    }

    public virtual DbSet<Bus> Buses { get; set; }
    public virtual DbSet<Driver> Drivers { get; set; }
    public virtual DbSet<Line> Lines { get; set; }
}

根据:https://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/creating-a-more-complex-data-model-for-an-asp-net-mvc-application。 我通过创建ViewModel并更新BusController来处理Bus&lt; - &gt; Driver连接。我可以使用复选框(驱动程序列表)正确创建和编辑总线。 但是,我有一个问题是使用Bus&lt; - &gt; Lines。

ViewModel文件夹由3个类组成(AssignedDriverData,BusIndexData,AssignedLineData):

public class AssignedDriverData
{
    public int DriverID { get; set; }
    public string DriverName { get; set; }
    public string DriverSurname { get; set; }

    public string DriverInfo
    {
        get
        {
            return DriverName + " " + DriverSurname;
        }
    }
    public bool Assigned { get; set; }
}

public class BusIndexData
{
    public IEnumerable<Bus> Buses { get; set; }
    public IEnumerable<Driver> Drivers { get; set; }
    public IEnumerable<Line> Lines { get; set; }
}

public class AssignedLineData
{
    public int LineID { get; set; }
    public int LineNumber { get; set; }
    public string Direction { get; set; }

    public string LineInfo
    {
        get
        {
            return LineNumber + ": " + Direction;
        }
    }
    public bool Assigned { get; set; }
}

BusController(包括更改行创建和编辑):

public class BusesController : Controller
{
    private ModelEntities db = new ModelEntities();

    // GET: Buses
    public ActionResult Index()
    {
        return View(db.Buses.ToList());
    }

    // GET: Buses/Details/5
    public ActionResult Details(int? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        Bus bus = db.Buses.Find(id);
        if (bus == null)
        {
            return HttpNotFound();
        }
        return View(bus);
    }

    // GET: Buses/Create
    public ActionResult Create()
    {
        //***************** adding drivers  ******************//
        var bus = new Bus();
        bus.Drivers = new List<Driver>();
        PopulateAssignedDriverData(bus);

        bus.Lines = new List<Line>();   //********* adding lines*********************//
        PopulateAssignedLineData(bus); //********* adding lines*********************//
        //************************************************//
        return View();
    }

    // POST: Buses/Create
    // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
    // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create([Bind(Include = "BusID,RegNum,Status")] Bus bus, string[] selectedDrivers, string[] selectedLines)
    {

        //******************* adding drivers **********************//
        if (selectedDrivers != null)
        {
            bus.Drivers = new List<Driver>();
            foreach (var course in selectedDrivers)
            {
                var driverToAdd = db.Drivers.Find(int.Parse(course));
                bus.Drivers.Add(driverToAdd);
            }
        }
        //************************************************//


        //******************* adding lines **********************//
        if (selectedLines != null)
        {
            bus.Lines = new List<Line>();
            foreach (var line in selectedLines)
            {
                var lineToAdd = db.Lines.Find(int.Parse(line));
                bus.Lines.Add(lineToAdd);
            }
        }
        //************************************************//


        if (ModelState.IsValid)
        {
            db.Buses.Add(bus);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        //************************************************//
        PopulateAssignedDriverData(bus);
        PopulateAssignedLineData(bus);
        //************************************************//
        return View(bus);
    }

    // GET: Buses/Edit/5
    public ActionResult Edit(int? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }

        //************** editing drivers ********************//
        Bus bus = db.Buses
            .Include(i => i.Drivers)
            .Include(i => i.Lines) //****** for editing lines ******//
            .Where(i => i.BusID == id)
            .Single();
        PopulateAssignedDriverData(bus);
        //************************************************//


        if (bus == null)
        {
            return HttpNotFound();
        }
        return View(bus);
    }

    // POST: Buses/Edit/5
    // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
    // more details see http://go.microsoft.com/fwlink/?LinkId=317598.


    //************** editing with drivers and lines ********************//

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Edit(int? id, string[] selectedDrivers, string[] selectedLines)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        var busToUpdate = db.Buses
           .Include(i => i.Drivers)
           .Include(i => i.Lines) //****** added for lines *******//
           .Where(i => i.BusID == id)
           .Single();

        if (TryUpdateModel(busToUpdate, "",
           new string[] { "BusID,RegNum,Status" }))
        {
            try
            {
                UpdateBusDrivers(selectedDrivers, busToUpdate);
                UpdateBusDrivers(selectedLines, busToUpdate); //****** added for lines *******//
                db.SaveChanges();

                return RedirectToAction("Index");
            }
            catch (RetryLimitExceededException /* dex */)
            {
                //Log the error (uncomment dex variable name and add a line here to write a log.
                ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
            }
        }
        PopulateAssignedDriverData(busToUpdate);
        PopulateAssignedLineData(busToUpdate); //****** added for lines *******//
        return View(busToUpdate);
    }
    //************************************************//


    // GET: Buses/Delete/5
    public ActionResult Delete(int? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        Bus bus = db.Buses.Find(id);
        if (bus == null)
        {
            return HttpNotFound();
        }
        return View(bus);
    }

    // POST: Buses/Delete/5
    [HttpPost, ActionName("Delete")]
    [ValidateAntiForgeryToken]
    public ActionResult DeleteConfirmed(int id)
    {
        Bus bus = db.Buses.Find(id);
        db.Buses.Remove(bus);
        db.SaveChanges();
        return RedirectToAction("Index");
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            db.Dispose();
        }
        base.Dispose(disposing);
    }


    //********************** adding drivers ******************//
    private void PopulateAssignedDriverData(Bus bus)
    {
        var allDrivers = db.Drivers;
        var busDrivers = new HashSet<int>(bus.Drivers.Select(c => c.DriverID));
        var viewModel = new List<AssignedDriverData>();
        foreach (var driver in allDrivers)
        {
            viewModel.Add(new AssignedDriverData
            {
                DriverID = driver.DriverID,
                DriverName = driver.DriverName,
                DriverSurname = driver.DriverSurname,
                Assigned = busDrivers.Contains(driver.DriverID)
            });
        }
        ViewBag.Drivers = viewModel;
    }
    //************************************************//



    //**************** editing drivers ***********************//
    private void UpdateBusDrivers(string[] selectedDrivers, Bus busToUpdate)
    {
        if (selectedDrivers == null)
        {
            busToUpdate.Drivers = new List<Driver>();
            return;
        }

        var selectedDriversHS = new HashSet<string>(selectedDrivers);
        var busDrivers = new HashSet<int>
            (busToUpdate.Drivers.Select(c => c.DriverID));
        foreach (var driver in db.Drivers)
        {
            if (selectedDriversHS.Contains(driver.DriverID.ToString()))
            {
                if (!busDrivers.Contains(driver.DriverID))
                {
                    busToUpdate.Drivers.Add(driver);
                }
            }
            else
            {
                if (busDrivers.Contains(driver.DriverID))
                {
                    busToUpdate.Drivers.Remove(driver);
                }
            }
        }
    }
    //************************************************//



    //********************** adding lines ******************//
    private void PopulateAssignedLineData(Bus bus)
    {
        var allLines = db.Lines;
        var busLines = new HashSet<int>(bus.Lines.Select(c => c.LineID));
        var viewModel = new List<AssignedLineData>();
        foreach (var line in allLines)
        {
            viewModel.Add(new AssignedLineData
            {
                LineID = line.LineID,
                Direction = line.Direction,
                LineNumber = line.LineNumber,
                Assigned = busLines.Contains(line.LineID)
            });
        }
        ViewBag.Lines = viewModel;
    }
    //************************************************//

    //**************** editing lines ***********************//
    private void UpdateBusLines(string[] selectedLines, Bus busToUpdate)
    {
        if (selectedLines == null)
        {
            busToUpdate.Lines = new List<Line>();
            return;
        }

        var selectedLinesHS = new HashSet<string>(selectedLines);
        var busLines = new HashSet<int>
            (busToUpdate.Lines.Select(c => c.LineID));
        foreach (var line in db.Lines)
        {
            if (selectedLinesHS.Contains(line.LineID.ToString()))
            {
                if (!busLines.Contains(line.LineID))
                {
                    busToUpdate.Lines.Add(line);
                }
            }
            else
            {
                if (busLines.Contains(line.LineID))
                {
                    busToUpdate.Lines.Remove(line);
                }
            }
        }
    }
    //************************************************//
 }

不幸的是,向总线添加任何行都失败了。 如何处理总线表的这2个多对多关系? 我很欣赏你的提示;) KB

1 个答案:

答案 0 :(得分:1)

您是否阅读了Fluent API?

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Bus>().HasMany(b => b.Drivers).WithMany(d => d.Buses).Map(m =>
            {
                m.MapLeftKey("BusId");
                m.MapRightKey("DriverID");
                m.ToTable("BusDriverJoinTable");
            });
        modelBuilder.Entity<Bus>().HasMany(b => b.Lines).WithMany(l=>l.Buses).Map(m =>
        {
            m.MapLeftKey("BusId");
            m.MapRightKey("LineID");
            m.ToTable("BusLineJoinTable");
        });
    }