2014-10-28 18 views
28

Tôi có 2 loại sau đây:Nhận tài sản thực thể chuyển hướng sau khi chèn

public class Reward 
{ 
    public int Id { get; set; } 
    public int CampaignId { get; set; 
    public virtual Campaign Campaign { get; set; } 
} 

public class Campaign 
{ 
    public int Id { get; set; } 
    public virtual ICollection<Reward> Rewards { get; set; } 
} 

Với điều này tôi có tất cả những thứ cần thiết hiển nhiên như một DbContext và ánh xạ.

Bây giờ chúng ta hãy nói rằng tôi tạo ra một thực thể thưởng và chèn nó như thế này:

var reward = new Reward { CampaignId = 1 }; 
context.Set<Reward>().Add(reward); 
context.SaveChanges(); 

reward = context.Set<Reward>().SingleOrDefault(a => a.Id == reward.Id); 
//reward.Campaign is null 

Tôi rõ ràng là có một chiến dịch với Id 1 để hạn chế FK là hạnh phúc. Sau lần chèn này, thực thể thưởng của tôi có bộ ID nhận dạng mới. Bây giờ vấn đề là phần thưởng vẫn chỉ là thực thể Phần thưởng mà tôi đã tạo. Và với điều này, thuộc tính reward.Campaign rỗng. Có vẻ như EF đang giữ các thực thể được chèn vào trong bộ nhớ, và khi tôi làm một .SingleOrDefault (a => a.Id == reward.Id) nó đơn giản trả về thực thể trong bộ nhớ, chứ không phải một proxy mới. Đây có lẽ là một điều tốt.

Vì vậy, câu hỏi là: Làm cách nào để truy cập hoặc tải thuộc tính điều hướng sau khi chèn hoặc nhận proxy mới có thuộc tính điều hướng là proxy.

Tôi có thể chèn sai không?

+0

không lập bản đồ của bạn trông như thế nào? – Maritim

+0

có thể trùng lặp với [Entity Framework: Tôi đặt khóa ngoại, SaveChanges rồi truy cập thuộc tính điều hướng, nhưng nó không tải thực thể liên quan. Tại sao không?] (Http://stackoverflow.com/questions/15552891/entity-framework-i-set-the-foreign-key-savechanges-then-access-the-navigation) – Colin

Trả lời

48

Nếu tôi hiểu chính xác bạn, bạn đang cố gắng háo hức tải một thuộc tính phức tạp sau khi thiết lập mối quan hệ thông qua một thuộc tính khóa ngoài.

SaveChanges() không làm bất kỳ điều gì trong cách tải các thuộc tính phức tạp. Tối đa, nó sẽ thiết lập thuộc tính khóa chính của bạn nếu bạn đang thêm các đối tượng mới.

Đường dây của bạn reward = context.Set<Reward>().SingleOrDefault(a => a.Id == reward.Id); cũng không làm gì theo cách tải Campaign vì đối tượng phần thưởng của bạn không được đính kèm theo ngữ cảnh. Bạn cần phải rõ ràng yêu cầu EF tải đối tượng phức tạp đó hoặc đính kèm đối tượng đó để cho phép tải chậm hoạt động.

Vì vậy, sau khi bạn context.SaveChanges(); bạn có ba tùy chọn để tải reward.Campaign:

  1. Attach() phần thưởng dành cho bối cảnh để Campaign có thể được nạp một cách lười biếng (nạp khi truy cập)

    context.Rewards.Attach(reward); 
    

    Lưu ý: Bạn sẽ chỉ có thể tải một cách lười biếng reward.Campaign trong phạm vi của ngữ cảnh để nếu bạn không truy cập bất kỳ thuộc tính nào trong vòng đời ngữ cảnh, sử dụng tùy chọn 2 hoặc 3.

  2. thủ Load() các Campaign tài sản

    context.Entry(reward).Reference(c => c.Campaign).Load(); 
    
  3. thủ Include() các Campaign tài sản

    reward = context.Rewards.Include("Campaigns") 
        .SingleOrDefault(r => r.Id == reward.Id); 
    

    Mặc dù, tôi muốn đề nghị Load kể từ khi bạn đã có reward trong ký ức.

Kiểm tra phần Tải đối tượng liên quan trên this msdn doc để biết thêm thông tin.

+4

Tùy chọn thứ hai là tốt nhất cho tôi cũng. –

+2

tùy chọn đầu tiên không hoạt động đối với tôi –

9

Khi bạn đang tạo đối tượng rewardnew Reward(), EF không có proxy. Thay vào đó, tạo ra nó bằng cách sử DbSet.Create như thế này:

var reward = context.Set<Reward>().Create(); 
reward.CampaignId = 5; 
context.SaveChanges(); 

Tiếp gắn nó vào DbSet của bạn:

context.Rewards.Attach(reward); 

Cuối cùng, bây giờ bạn có thể sử dụng tải lười biếng để có được các đơn vị liên quan:

var campaign = reward.Campaign; 
1

Bạn đã thử sử dụng Include()? Một cái gì đó như thế này:

reward = context.Set<Reward>().Include("Campaigns").SingleOrDefault(a => a.Id == reward.Id); 
1

Tôi có một giải pháp đơn giản xung quanh vấn đề.

thay vì thêm campaignid đến phần thưởng, thêm Object chiến dịch .. vậy:

var _campaign = context.Campaign.First(c=>c.Id == 1);//how ever you get the '1' 
var reward = new Reward { Campaign = _campaign }; 
context.Set<Reward>().Add(reward); 
context.SaveChanges(); 

//reward.Campaign is not null 

khung Entity làm tất cả việc nặng nhọc ở đây. Bạn có thể nghĩ rằng đó là một sự lãng phí để tải toàn bộ đối tượng Chiến dịch nhưng nếu bạn đang sử dụng nó (từ những gì nó trông giống như, có vẻ như bạn đang có) thì tôi không thấy lý do tại sao không. Bạn thậm chí có thể sử dụng bao gồm tuyên bố khi lấy nó ở trên nếu bạn cần truy cập vào thuộc tính chuyển hướng từ đối tượng vận động ...

var _campaign = context.Campaign.include(/*what ever you may require*/).First(c=>c.Id = 1); 
Các vấn đề liên quan