2010-08-03 23 views
7

Tôi đoán điều này là không thể, nhưng tôi sẽ ném nó ra có anyway. Có thể sử dụng CreateSourceQuery khi lập trình với API EF4 CodeFirst, trong CTP4 không? Tôi muốn háo hức tính tải gắn liền với một tập hợp các thuộc tính, như thế này:Sử dụng CreateSourceQuery trong Mã CTP4 Đầu tiên

var sourceQuery = this.CurrentInvoice.PropertyInvoices.CreateSourceQuery(); 
sourceQuery.Include("Property").ToList(); 

Nhưng tất nhiên CreateSourceQuery được định nghĩa trên EntityCollection<T>, trong khi CodeFirst sử dụng đồng bằng cũ ICollection (rõ ràng). Có cách nào để chuyển đổi không?

Tôi đã nhận được thông tin bên dưới, nhưng đó không phải là những gì tôi đang tìm kiếm. Bất cứ ai cũng biết làm thế nào để đi từ những gì dưới đây để những gì ở trên (code dưới đây là từ một lớp kế thừa DbContext)?

ObjectSet<Person> OSPeople = base.ObjectContext.CreateObjectSet<Person>(); 
OSPeople.Include(Pinner => Pinner.Books).ToList(); 

Cảm ơn!

EDIT: đây là phiên bản của tôi về giải pháp được đăng bởi zeeshanhirani - người đặt trước bằng cách tuyệt vời!

dynamic result; 

if (invoice.PropertyInvoices is EntityCollection<PropertyInvoice>) 
    result = (invoices.PropertyInvoices as EntityCollection<PropertyInvoice>).CreateSourceQuery().Yadda.Yadda.Yadda 
else 
    //must be a unit test! 
    result = invoices.PropertyInvoices; 

return result.ToList(); 

EDIT2:

Ok, tôi chỉ nhận ra rằng bạn không thể cử phương pháp khuyến nông trong khi sử dụng năng động. Vì vậy, tôi đoán chúng tôi không khá năng động như Ruby, nhưng ví dụ trên có thể dễ dàng sửa đổi để ứng xử với hạn chế này

EDIT3:

Như đã đề cập trong bài đăng blog zeeshanhirani, chỉ các công trình này nếu (và chỉ khi bạn có proxy hỗ trợ thay đổi, sẽ được tạo nếu tất cả thuộc tính của bạn được khai báo là ảo. Đây là một phiên bản khác của phương pháp có thể trông như thế nào để sử dụng CreateSourceQuery với POCOs

public class Person { 
    public virtual int ID { get; set; } 
    public virtual string FName { get; set; } 
    public virtual string LName { get; set; } 
    public virtual double Weight { get; set; } 
    public virtual ICollection<Book> Books { get; set; } 
} 

public class Book { 
    public virtual int ID { get; set; } 
    public virtual string Title { get; set; } 
    public virtual int Pages { get; set; } 
    public virtual int OwnerID { get; set; } 
    public virtual ICollection<Genre> Genres { get; set; } 
    public virtual Person Owner { get; set; } 
} 

public class Genre { 
    public virtual int ID { get; set; } 
    public virtual string Name { get; set; } 
    public virtual Genre ParentGenre { get; set; } 
    public virtual ICollection<Book> Books { get; set; } 
} 

public class BookContext : DbContext { 
    public void PrimeBooksCollectionToIncludeGenres(Person P) { 
     if (P.Books is EntityCollection<Book>) 
      (P.Books as EntityCollection<Book>).CreateSourceQuery().Include(b => b.Genres).ToList(); 
    } 
+1

Nhìn vào loại thực tế (thực hiện 'ICollection'). Bạn có thể cast? –

+0

Vâng, craig, bạn đã có nó tất cả cùng. –

Trả lời

3

Chắc chắn là có thể làm như vậy. Nếu bạn đã đánh dấu thuộc tính thu thập của mình với từ khóa virtual, thì khi chạy, bạn có thể loại ICollectionEntityCollection hỗ trợ CreateSourceQuery và tất cả các tính năng đi kèm với trình tạo mã mặc định. Đây là cách tôi sẽ làm điều đó.

public class Invoice 
{ 
    public virtual ICollection PropertyInvoices{get;set} 
} 

dynamic invoice = this.Invoice; 
dynamic invoice = invoice.PropertyInvoices.CreateSourceQuery().Include("Property"); 

Tôi đã viết một bài đăng trên blog về nội dung tương tự. Chỉ cần lưu ý rằng thực tiễn tốt không phải dựa vào việc thực hiện bên trong của ICollection được chuyển đổi thành EntityCollection. dưới đây là bài viết trên blog bạn có thể thấy hữu ích

http://weblogs.asp.net/zeeshanhirani/archive/2010/03/24/registering-with-associationchanged-event-on-poco-with-change-tracking-proxy.aspx

+0

Aha - thiên tài! Tôi sẽ làm như vậy (bên trong phương pháp DAO, hoặc bất cứ nơi nào bạn xây dựng truy vấn) kết quả động; nếu (invoice.PropertyInvoices là EntityCollection ) result = (invoice.PropertyInvoices là EntityCollection ). CreateSourceQuery(). Yadda.Yadda.Yadda else // phải là một thử nghiệm đơn vị! result = invoice.PropertyInvoices; kết quả trả về.ToList(); –

+0

Yuck - hãy viết lại như một câu trả lời để có được định dạng tốt hơn. Hey, trên một ghi chú khác - I * LOVE * cuốn sách của bạn. Tôi vừa hoàn thành nó - rực rỡ! Làm tốt. –

+0

Cảm ơn. Bây giờ bạn nợ tôi một bài đánh giá trên amazon. Không phải là nó giúp tôi kiếm tiền trong cuốn sách ngoài Apress kiếm tiền, nó sẽ giúp chúng tôi viết phiên bản thứ hai của cuốn sách. – zeeshanhirani

4

Có thể thêm một phương pháp để bạn bối cảnh có nguồn gốc tạo ra một truy vấn nguồn cho một hướng nhất định trên một thể hiện thực thể. Để làm điều này bạn cần phải tận dụng các ObjectContext tiềm ẩn trong đó bao gồm một người quản lý mối quan hệ đó cho thấy bộ sưu tập thực thể cơ bản/tài liệu tham khảo cho mỗi hướng:

public ObjectQuery<T> CreateNavigationSourceQuery<T>(object entity, string navigationProperty) 
{ 
    var ose = this.ObjectContext.ObjectStateManager.GetObjectStateEntry(entity); 
    var rm = this.ObjectContext.ObjectStateManager.GetRelationshipManager(entity); 

    var entityType = (EntityType)ose.EntitySet.ElementType; 
    var navigation = entityType.NavigationProperties[navigationProperty]; 

    var relatedEnd = rm.GetRelatedEnd(navigation.RelationshipType.FullName, navigation.ToEndMember.Name); 

    return ((dynamic)relatedEnd).CreateSourceQuery(); 
} 

Bạn có thể nhận được ưa thích và chấp nhận một Func cho các tài sản chuyển hướng để tránh việc để chỉ định T, nhưng dưới đây là cách sử dụng chức năng trên:

using (var ctx = new ProductCatalog()) 
{ 
    var food = ctx.Categories.Find("FOOD"); 
    var foodsCount = ctx.CreateNavigationSourceQuery<Product>(food, "Products").Count(); 
} 

Hy vọng điều này sẽ hữu ích!

~ Rowan

+0

Wow - cách tuyệt vời - cảm ơn Rowan và chào mừng bạn đến với StackOverflow. –

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