2012-10-25 13 views
32

Tôi đang cố gắng sử dụng EF với Mã đầu tiên và API Web. Tôi không có bất kỳ vấn đề gì cho đến khi tôi bắt đầu theo dõi các mối quan hệ Nhiều-nhiều. Khi tôi cố gắng để thực hiện phương pháp web api sau dưới đây tôi nhận được thông báo lỗi sau:Nối tiếp các đối tượng Khung thực thể có mối quan hệ một đến nhiều

public class TagsController : ApiController 
{ 

     private BlogDataContext db = new BlogDataContext(); 

     // GET api/Tags 
     public IEnumerable<Tag> GetTags() 
     { 
      return db.Tags.AsEnumerable(); 
     } 
} 

tôi nhận được lỗi sau:

'System.Data.Entity.DynamicProxies.Tag_FF17EDDE6893000F7672649A39962DB0CA591C699DDB73E8C2A56203ED7C7B6D' with data contract name 'Tag_FF17EDDE6893000F7672649A39962DB0CA591C699DDB73E8C2A56203ED7C7B6D: http://schemas.datacontract.org/2004/07/System.Data.Entity.DynamicProxies ' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.

Tôi đã đọc một số SO bài viết (article 1, article 2) mà sửa chữa là thêm thuộc tính sau:

[DataContract (IsReference=true)]

nhưng điều này không có hiệu lực. Cũng sử dụng [IgnoreDataMember] không có hiệu lực. Tùy chọn duy nhất có vẻ hoạt động là đặt Configuration.ProxyCreationEnabled thành false. Đây có phải là lựa chọn duy nhất của tôi không? Tui bỏ lỡ điều gì vậy?

đối tượng mẫu POCO:

Tag

[DataContract(IsReference = true)] 
public class Tag 
{ 
     public Tag() 
     { 
      this.Blogs = new HashSet<Blog>(); 
     } 

     [Key] 
     [DataMember] 
     public int Id { get; set; } 

     [DataMember] 
     public string Name { get; set; } 

     [IgnoreDataMember] 
     public virtual ICollection<Blog> Blogs { get; set; } 
} 

Blog

[DataContract(IsReference = true)] 
public class Blog 
{ 
    public Blog() 
    { 
     this.Tags = new HashSet<Tag>(); 
    } 

    [Key] 
    [DataMember] 
    public int Id { get; set; } 

    [DataMember] 
    public string Name { get; set; } 

    [IgnoreDataMember] 
    public virtual ICollection<Tag> Tags { get; set; } 
} 
+1

tôi đã có vấn đề chính xác cùng, và tôi thấy giải pháp duy nhất là như bạn, và Erik Philips, đã nói. Để tắt tính năng tạo proxy. Lý do 'IgnoreDataMember' không có hiệu lực là vì vấn đề là với việc tạo proxy, không phải là sự tuần tự hóa' ICollection' của 'Thẻ'. –

+0

Tôi có cùng một vấn đề, bạn đã giải quyết nó như thế nào? Khi tôi vô hiệu hóa tạo proxy sau đó tôi không thể có được các giá trị của phụ huynh, mà tôi cần nó. làm ơn giúp tôi. –

Trả lời

79

Khi bạn nhìn thấy một đối tượng như:

System.Data.Entity.DynamicProxies.Tag_FF17EDDE6893000F7672649A39962DB0CA591C699DDB73E8C2A56203ED7C7B6D

Đây là thời gian chạy EF Phiên bản được tạo của một số proxy đối với những gì thường được coi là đối tượng POCO.

Khung đối tượng đã tạo đối tượng này vì nó theo dõi khi các đối tượng đã thay đổi để khi bạn gọi .SaveChanges(), nó có thể tối ưu hóa việc cần làm. Sự sụp đổ của điều này là bạn không thực sự sử dụng đối tượng cụ thể mà bạn đã định nghĩa, do đó các Hợp đồng và Khung dữ liệu (Json.net) không thể sử dụng chúng như đối tượng POCO ban đầu của bạn.

Để Ngăn EF từ trở về đối tượng này, bạn có hai lựa chọn (ATM):

Thứ nhất, Try turning off Proxy object creation on your DbContext.

DbContext.Configuration.ProxyCreationEnabled = false; 

Điều này sẽ vô hiệu hóa hoàn toàn việc tạo đối tượng Proxy cho mọi truy vấn đến DbContext cụ thể. (Điều này không ảnh hưởng đến đối tượng được lưu trong bộ nhớ cache trong ObjectContext).

Thứ hai, sử dụng EntityFramework 5.0+ với AsNoTracking() (ProxyCreationEnabled là vẫn có sẵn trong EF 5.0 cũng)

Bạn cũng sẽ có thể

DbContext.Persons.AsNoTracking().FirstOrDefault(); 

hoặc

DbContext.Persons. 
    .Include(i => i.Parents) 
    .AsNoTracking() 
    .FirstOrDefault(); 

Thay vì toàn cầu vô hiệu hóa tạo proxy cho các DbContext, điều này chỉ tắt tính mỗi truy vấn. (này DOES ảnh hưởng đến đối tượng cache trong ObjectContext, nó không được lưu trữ)

+4

Và tôi nghĩ Code First được thiết kế cho POCO ... –

+1

Vấn đề là để Entity Framework theo dõi các thay đổi, khi bạn yêu cầu nó cho một Instance, nó cung cấp một cá thể được bao bọc để kích hoạt theo dõi thay đổi. Ví dụ được bọc gần như luôn luôn không thể được tuần tự hóa. –

+0

Anh hùng của tôi !!! – Hugo

2

tôi muốn rời khỏi Proxy tạo inteact, và thấy rằng việc sử dụng các ProxyDataContractResolver dường như giải quyết vấn đề đối với tôi. Xem msdn để tham khảo về cách sử dụng nó trong wcf, không chính xác là WebAPI, nhưng sẽ giúp bạn đi dọc theo con đường bên phải.

+1

Bạn có thể giải thích cho tôi cách sử dụng ProxyDataContractResolver để sereialize thực thể poco không? Ví dụ duy nhất tôi quản lý để tìm WCF liên quan và tôi không thể tìm ra cách nó hoạt động. –

0
db.Configuration.ProxyCreationEnabled = false; 

sẽ giải quyết vấn đề của bạn