2011-03-24 45 views
8

hiện tôi mới để EF 4 và đây là những gì tôi đã làm cho đến nay:đối tượng Insert mới với đối tượng

  • Tạo một tập tin edmx dựa trên cơ sở dữ liệu của tôi
  • Tạo một thế hệ mã cho đối tượng của tôi (POCO). Bây giờ tôi có một model1.tt, khi mở rộng tôi thấy al lớp học của tôi
  • Tạo một kho lưu trữ cho mỗi lớp, dựa trên IRepository

Bây giờ, tôi đang làm việc với hai đối tượng, A và B. Object A có một thuộc tính kiểu B. Trong winform của tôi, tôi có một combo chứa đầy các đối tượng kiểu B. Khi nhấn nút save, một cá thể mới của lớp A được tạo và tất cả các thuộc tính được thiết lập. Thuộc tính đối tượng B được đặt như sau:

objectA.myObjectB = (objectB)cmbBObjects.selectedItem; 

Sau đó, tôi tạo kho lưu trữ cho đối tượngA và gọi phương thức lưu. Trong phương pháp lưu này, tôi có mã này ±

public bool Save(ObjectA obj) 
{ 
    using(MyContext context = new MyContext()) 
    { 
    context.objectAs.AddObject(obj); 
    context.SaveChanges(); 
    } 
} 

Mã này, lưu một mục mới vào cơ sở dữ liệu, nhưng nó cũng tạo bản ghi mới cho đối tượng B! Tôi không muốn điều này, bởi vì đối tượng B đã tồn tại trong cơ sở dữ liệu! (Tôi đã chọn cái này từ combobox).

Đây là cách tôi điền vào combobox của tôi:

Trong kho objectB:

public IList<ObjectB> GetAll() 
{ 
    using(MyContext context = new MyContext()) 
    { 
     IList<ObjectB> objects = context.objectBs.ToList(); 
     return objects; 
    } 
} 

Ở dạng của tôi:

ObjectBRepository rep = new ObjectBRepository(); 
IList<ObjectB> objects = rep.GetAll; 

cmbBObjects.Datasource = objects; 
// etc.. 

Vì vậy, câu hỏi của tôi là, những gì tôi phải làm thế nào để lưu đối tượng A mà không tạo bản ghi mới cho đối tượngB?

Trả lời

17

Nếu bạn không muốn chèn objectB, bạn phải thông báo cho EF về điều đó. Khi bạn gọi context.objectAs.AddObject(obj) cho objectA bạn đang nói: Tôi muốn chèn objectA và tất cả các phụ thuộc của nó. Nhưng rõ ràng bạn không muốn lưu phụ thuộc, do đó bạn phải:

  • Tải objectB từ DB trước khi thêm nó vào objectA.Trong trường hợp như vậy EF sẽ biết rằng objectB là đối tượng hiện tại và nó sẽ không chèn lại nó.
  • Đính kèm objectB vào ngữ cảnh trước khi thêm vào objectA. ObjectB sẽ được xử lý như hiện tại nhưng không thay đổi.
  • Đặt trạng thái objectB sau khi chèn objectA. Bạn có thể làm điều đó bằng cách gọi: context.ObjectStateManager.ChangeObjectState(objectB, EntityState.Unchanged)

Ví dụ về các đề nghị nắm tay:

var id = objectB.Id; 
objectA.myObjectB = context.ObjectBs.SingleOrDefault(o => o.Id == id); 

Ví dụ về các đề nghị thứ hai:

context.ObjectBs.Attach(objectB); 
objectA.myObjectB = objectB; 

Ví dụ về các gợi ý thứ ba:

objectA.myObjectB = objectB; 
context.ObjectAs.AddObject(objectA); 
context.ObjectStateManager.ChangeObjectState(objectB, EntityState.Unchanged); 
+0

Cảm ơn bạn. Tôi không hiểu gợi ý 1. Đề xuất thứ hai: Trong kho lưu trữ của objectA, làm một cái gì đó như: 'var obj = context.ObjectB.where (b => b.Id == objectA.myObjectB.Id) .firstOrDefault() ; context.ObjectA.Attach (obj); 'Điều này có đúng không? – Martijn

+0

Tôi đã chỉnh sửa câu trả lời của mình. –

+0

@LadislavMrnka: Chính xác, tất cả các tùy chọn có thể có và tôi cho rằng tùy chọn thứ hai là tốt nhất cho ví dụ trên. +1 –

1

Tôi cho rằng vấn đề ở hàng sau:

objectA.myObjectB = (objectB)cmbBObjects.selectedItem; 

Bởi vì kết quả (objectB)cmbBObjects.selectedItem tách ra từ DataContext khuôn khổ thực thể tạo thể hiện mới. Thay vì điều này, bạn có thể:

1.Assign objectB id để objectA

var b = (objectB)cmbBObjects.selectedItem; 
objectA.myObjectBId = b.Id; 

2.Or objectB tải từ DataContext và hơn gán cho objectA:

var b = (objectB)cmbBObjects.selectedItem; 
var dcB = context.ObjectBs.Single(x=> x.Id == b.Id); 
objectA.myObjectB = dcB; 

Chỉ cần cố gắng gợi ý của tôi và trở lại với kết quả, bởi vì tôi không biết chính xác.

Hy vọng trợ giúp này.

+0

objectA không có id đối tượng trực tiếp, mu này st được thiết lập như sau (tôi giả sử) 'objectA..myObjectB.Id = b.Id' Nhưng, tôi nghĩ rằng điều này sẽ ném một đối sốNull ngoại lệ, vì thuộc tính' .myObjectB' không được thiết lập. Giải pháp thứ hai: Tôi không nghĩ rằng tôi muốn bối cảnh của tôi trong winform, tôi muốn giữ đối tượng đó trong kho của tôi. – Martijn

+0

@Martijn: Được rồi, hơn bạn nên đi theo cách thứ hai do tôi đề xuất (nạp đối tượngB từ dataContext và gán cho objectA). –

Các vấn đề liên quan