2011-12-16 40 views
8

Trong .NET Entity Framework, cách tốt nhất để có một bảng nối (tùy chỉnh) với các thuộc tính phụ (không phải là id) và/hoặc kết hợp bảng nối kết này với những người khác thông qua mô hình riêng biệt? Trong Ruby on Rails chúng ta có thể có một mô hình cho bảng tham gia, như:Rails tương đương nhiều trong ASP.NET MVC3

Item.rb (model) 
:has_many => :buyers, :through=>:invoice 
... 

Buyers.rb (model) 
:has_many => :items, :through=>:invoice 
... 

Invoice.rb (model) 
:belongs_to :item 
:belongs_to :buyer 
.... 

Sau đó, chúng ta có thể sử dụng: Item.first.buyers, Buyers.first.itemsBuyer.create(:items=>Item.create(:name=>'random')), vv giống như khi chúng ta sử dụng tự động tham gia bảng mà không có mô hình (sử dụng has_and_belongs_to_many).

Trong hộp thoại "Thêm liên kết" của Visual Studio 2010, nếu chúng tôi chọn đa dạng là * (Nhiều) không có tùy chọn để chọn bảng tham gia (với mô hình). Có cách nào để thực hiện thủ công không?

Trả lời

6

Có, bạn có thể tải một thứ khá gần. Tôi không hoàn toàn chắc chắn làm thế nào để thiết lập này trong các nhà thiết kế kể từ khi tôi chỉ làm việc với codefirst.

Dưới đây là một ví dụ:

Sinh viên -> StudentFloor < - Tầng

public class Student 
{ 
    public int Id { get; set; } 
    // ... properties ... 

    // Navigation property to your link table 
    public virtual ICollection<StudentFloor> StudentFloors { get; set; } 

    // If you wanted to have a property direct to the floors, just add this: 
    public IEnumerable<Floor> Floors 
    { 
     get 
     { 
      return StudentFloors.Select(ft => ft.Floor); 
     } 
    } 
} 

Bảng liên kết:

public class StudentFloor 
{ 
    #region Composite Keys 

    // Be sure to set the column order and key attributes. 
    // Convention will link them to the navigation properties 
    // below. The database table will be created with a 
    // compound key. 

    [Key, Column(Order = 0)] 
    public int StudentId { get; set; } 

    [Key, Column(Order = 1)] 
    public int FloorId { get; set; } 

    #endregion 

    // Here's the custom data stored in the link table 

    [Required, StringLength(30)] 
    public string Room { get; set; } 

    [Required] 
    public DateTime Checkin { get; set; } 

    // Navigation properties to the outer tables 
    [Required] 
    public virtual Student Student { get; set; } 

    [Required] 
    public virtual Floor Floor { get; set; } 

} 

Cuối cùng, phía bên kia của nhiều-nhiều:

public class Floor 
{ 
    public int Id { get; set; } 
    // ... Other properties. 

    public virtual ICollection<StudentFloor> StudentFloors { get; set; } 
} 
+0

Cảm ơn bạn đã nhập. Vui lòng kiểm tra phần cập nhật và cho tôi biết nếu mã trong bộ điều khiển có thể được làm mỏng hơn và kiểu dáng đẹp hơn. –

+0

Tôi đang tìm phần cập nhật với bộ điều khiển mà bạn đã đề cập ... không tìm thấy? – Leniency

+0

Thật tệ. Có vẻ như nó đã bị từ chối bởi những người dùng khác mặc dù nó chỉ là phần tiếp theo của câu trả lời của bạn. Hãy để tôi đặt nó trong một câu trả lời riêng biệt. –

0

CẬP NHẬT câu trả lời của Leniency:

Chúng tôi cũng có thể tạo hai mối quan hệ một-nhiều với Mô hình tiếp cận đầu tiên. Dù bằng cách nào chúng ta không thể có mô hình ràng buộc như xảy ra trong quan hệ M2M thuần túy (không có tải trọng hoặc các bảng kết nối thuần túy - PJT).

Ngoài ra, trong bộ điều khiển (giàn giáo), chúng tôi có thể sử dụng mô hình xem cho các hoạt động CRUD theo yêu cầu. Giả sử là, chúng ta có một FloorViewModel với định nghĩa sau đây:

public class FloorViewModel 
{ 
    private Model2Container context = new Model2Container(); 

    [Display(Name = "Student List")] 
    [Required(ErrorMessage = "Please select atleast one student from the list.")] 
    public int[] MyStudents { get; set; } 

    public Floor MyFloor { get; set; } 

    public MultiSelectList StudentsList { get; set; } 

    public StudentFloorJoin Join { get; set; } 

} 

Hành động tạo ra trong bộ điều khiển sẽ là:

// 
// GET: /Floor/Create 

public ActionResult Create() 
{ 
    var model = new FloorViewModel() { StudentsList = new MultiSelectList(context.Students, "Id", "Name") }; 
    return View(model); 
} 

// 
// POST: /Floor/Create 

[HttpPost] 
public ActionResult Create(FloorViewModel floor) 
{ 
    if (ModelState.IsValid) 
    { 
     context.Floors.Add(floor.MyFloor); 
     context.SaveChanges(); 
    } 
    foreach (var student in floor.MyStudents) 
    { 
     context.StudentFloorJoins.Add(new StudentFloorJoin() { Student = context.Students.Find(student), Floor = floor.MyFloor, Room = floor.Join.Room }); 
    } 
    if (ModelState.IsValid) 
    { 
     context.SaveChanges(); 
     return RedirectToAction("Index"); 
    } 
    context.Floors.Remove(floor.MyFloor); 
    floor.StudentsList = new MultiSelectList(context.Students, "Id", "Name", floor.MyStudents); 
    return View(floor); 
} 

và các hành động chỉnh sẽ là một cái gì đó như:

// 
// GET: /Floor/Edit 

public ActionResult Edit(int id) 
{ 
    Floor floor = context.Floors.Single(x => x.Id == id); 
    int[] ids = (from i in floor.StudentFloorJoins select i.Student.Id).ToArray(); 
    var model = new FloorViewModel() { StudentsList = new MultiSelectList(context.Students, "Id", "Name", ids), MyFloor = floor, Join = new StudentFloorJoin() { Room = floor.StudentFloorJoins.Count == 0 ? "" : floor.StudentFloorJoins.First().Room } }; 
    return View(model); 
} 

// 
// POST: /Floor/Edit 

[HttpPost] 
public ActionResult Edit(FloorViewModel floor) 
{ 
    if (ModelState.IsValid) 
    { 
     var item = floor.MyFloor; 
     var itemEntry1 = context.Entry<Floor>(item); 
     itemEntry1.State = EntityState.Modified; 
     var query = (from i in context.StudentFloorJoins where i.Floor.Id == item.Id select i.Id); 
     foreach (var studentfloor in query) 
     { 
      context.StudentFloorJoins.Remove(context.StudentFloorJoins.Find(studentfloor)); 
     } 
     context.SaveChanges(); 

     foreach (var student in floor.MyStudents) 
     { 
      context.StudentFloorJoins.Add(new StudentFloorJoin() { Student = context.Students.Find(student), Floor = floor.MyFloor, Room = floor.Join.Room }); 
     } 
     context.SaveChanges(); 
     return RedirectToAction("Index"); 
    } 
    floor.StudentsList = new MultiSelectList(context.Students, "Id", "Name", floor.MyStudents); 
    return View(floor); 
} 

Trong Xem, chúng tôi có thể gửi đối tượng của FloorModelView như:

@model ManyToManyAutoGen.Models.FloorViewModel 

@{ 
    ViewBag.Title = "Create"; 
} 

<h2>Create</h2> 

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script> 
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script> 

@using (Html.BeginForm()) { 
    @Html.ValidationSummary(true) 
    <fieldset> 
     <legend>Floor</legend> 

     @Html.Partial("_CreateOrEdit", Model) 

     <p> 
      <input type="submit" value="Create" /> 
     </p> 
    </fieldset> 
} 

<div> 
    @Html.ActionLink("Back to List", "Index") 
</div> 

và cuối cùng, phần _CreateOrEdit trông giống như:

@model ManyToManyAutoGen.Models.FloorViewModel 

@* This partial view defines form fields that will appear when creating and editing entities *@ 

<div class="editor-label"> 
    @Html.LabelFor(model => model.MyFloor.FloorName) 
</div> 
<div class="editor-field"> 
    @Html.EditorFor(model => model.MyFloor.FloorName) 
    @Html.ValidationMessageFor(model => model.MyFloor.FloorName) 
</div> 

<div class="editor-label"> 
    @Html.LabelFor(model => model.MyStudents) 
</div> 
<div class="editor-field"> 
    @Html.ListBoxFor(model => model.MyStudents, Model.StudentsList) 
    @Html.ValidationMessageFor(model => model.MyStudents) 
</div> 

<div class="editor-label"> 
    @Html.LabelFor(model => model.Join.First().Room) 
</div> 
<div class="editor-field"> 
    @Html.EditorFor(model => model.Join.First().Room) 
    @Html.ValidationMessageFor(model => model.Join) 
</div> 
Các vấn đề liên quan