2009-03-29 39 views
9

Tôi có một thực thể Foo trong Khuôn khổ thực thể. Nhưng tôi làm cho nó kế thừa từ IFoo để logic kinh doanh của tôi chỉ biết IFoo - do đó trừu tượng khung thực thể đi.Tôi có thể trừu tượng Khung thực thể khỏi các đối tượng của mình không?

Vấn đề là Foo có một bộ sưu tập gồm Bar pháp nhân. Và bộ sưu tập này thuộc loại EntityCollection<Bar>.

Nếu tôi đặt bộ sưu tập này trong IFoo như vậy, tôi thực hiện IFoo tùy thuộc vào Khuôn khổ thực thể. Vì vậy, tôi nghĩ đến việc đặt nó là ICollection<IBar>, nhưng điều này không biên dịch (một cách tự nhiên).

Giải pháp duy nhất tôi có thể nghĩ đến là thực hiện Foo cụ thể được tạo bởi nhà thiết kế Khung thực thể và thay đổi bộ sưu tập từ EntityCollection<Bar> thành ICollection<IBar> tại đó. Nhưng tôi sợ những suy nghĩ về những tác động này sẽ có trên Entity Framework "đằng sau hậu trường".

Có cách nào để tôi xác định IFooIBar độc lập với Khung thực thể trong khi vẫn duy trì FooBar làm thực thể EF thực hiện chúng? Do IFooIBar thậm chí có ý nghĩa không, nếu tôi không thể đạt được sự độc lập này mà tôi nhắm đến?

+0

Lý do chính xác bạn muốn IFoos và IBars thay vì Foos và Bars là gì? – Inferis

+0

Tôi đang hướng tới sự thiếu hiểu biết. Xem câu trả lời được chấp nhận bên dưới. – urig

Trả lời

8

Khái niệm chung mà bạn đang đề cập đến là "thiếu hiểu biết" (PI), mặc dù thường áp dụng trực tiếp cho thực thể chứ không phải mã tiêu thụ thực thể.

Trong mọi trường hợp, Hibernate và NHibernate nguyên bản hỗ trợ PI, nhưng phiên bản ban đầu của Khuôn khổ thực thể của Microsoft thì không.MS bắt được rất nhiều lỗi cho điều này và PI có lẽ là tính năng được thảo luận nhiều nhất # 1 cho phiên bản tiếp theo (bất cứ khi nào có).

Theo như những gì bạn đang cố gắng thực hiện với giao diện, bộ sưu tập Thanh có cần phải được sửa đổi sau khi nó được truy lục không? Nếu câu trả lời là có, không có câu trả lời dễ dàng. Ngay cả hiệp phương sai không thể giúp bạn ở đây vì ICollection<T> có phương thức Thêm.

Nếu bộ sưu tập chỉ đọc, thì bạn có thể xem xét việc hiển thị bộ sưu tập là IEnumerable<IBar>. Phương pháp Enumerable.Cast làm cho điều này khá thuận tiện.

interface IFoo 
{ 
    IEnumerable<IBar> Bars { get; } 
} 

partial class Foo : IFoo 
{ 
    IEnumerable<IBar> IFoo.Bars 
    { 
     get { return Bars.Cast<IBar>(); } 
    } 
} 

Ngoài ra, tôi biết at least one effort để làm cho hiện tại phiên bản của EF hỗ trợ kiên trì vô minh.

+0

Tại sao không thể sửa đổi? AttachTo có thể đính kèm đối tượng vào ngữ cảnh, nơi sau khi sửa đổi có thể được thực hiện. – aleemb

+0

EF 4 có thực hiện điều này không? – BigJoe714

2

Tôi là nhà phát triển Java, vì vậy tôi không thể nhận xét với bất kỳ cơ quan nào trên Khung thực thể. Tôi có thể nói với bạn rằng các giải pháp ORM như Hibernate làm cho nó có thể có sự bền vững POJO mà không cần phải dùng đến các lớp trừu tượng chung, các giao diện, hoặc sửa đổi mã byte. Nó xử lý các mối quan hệ như 1: m bạn trích dẫn cho Foo và Bar của bạn mà không cần phải sử dụng các lớp sưu tập đặc biệt.

Nước sốt đặc biệt được chia ra thành cấu hình ánh xạ và chính Hibernate.

Tôi đã đọc một chút về Khung thực thể cho thấy đây là giải pháp ORM với cùng mục tiêu: POCO kiên trì. Tôi không thấy bất kỳ đề cập đến giao diện. Tôi không thể thấy sự cần thiết cho họ từ ví dụ của bạn, bởi vì nó quá trừu tượng.

Tôi phỏng đoán rằng có thể có được sự độc lập giữa các đối tượng kinh doanh và tầng kiên trì mà không cần phải dùng đến các giao diện đó, bởi vì tôi biết Hibernate làm điều đó. Tôi muốn nói rằng giải pháp JDBC của Spring cũng hoàn thành nó, bởi vì không cần giao diện chung. Họ sử dụng một cấu trúc RowMapper để truyền dữ liệu ra khỏi một truy vấn và vào một đối tượng.

Tôi ước tôi có thể tư vấn cho bạn chính xác cách thực hiện nó bằng Entity Framework, nhưng có thể bạn sẽ biết rằng nó có thể được thực hiện.

+0

Cảm ơn bạn đã phản hồi chi tiết. Tôi đã có một trải nghiệm tích cực trong quá khứ với NHibernate, phiên bản .net của Hibernate của Java. Tôi không có chuyên gia về EF nhưng tôi hiểu rằng việc lập bản đồ của nó là thuộc tính dựa trên chứ không phải là bên ngoài trong một tệp XML. Đó là lý do tại sao tôi cần phải tóm tắt thông qua một giao diện. Tôi nghĩ rằng;) – urig

+0

Có lẽ bạn đã đúng. Tôi chỉ không thấy bất kỳ bằng chứng nào về điều đó trong một thời gian ngắn thông qua một bài viết của Google. Xin lỗi tôi không hữu ích hơn. – duffymo

2

Sử dụng một phần lớp để tách riêng logic và quy tắc của bạn khỏi các đối tượng EF được tạo tự động. Trong ví dụ bên dưới lớp FooEntityObject được chia làm hai bằng cách sử dụng từ khóa một phần. Tôi đã sử dụng kỹ thuật này trước với EF và LINQ to SQL. Các lớp một phần có thể được lưu trữ trong các tệp riêng biệt vì vậy nếu bạn tái tạo đối tượng EF của bạn một lần nữa mã tùy chỉnh của bạn không bị ghi đè lên.

interface IFoo 
{ 
    public ICollection<IBar> GetBars(); 
} 

public partial class FooEntityObject : IFoo 
{ 
    public ICollection<IBar> GetBars() 
    { 
     // convert EntityCollection<Bar> into ICollection<IBar> here 
    } 
} 


public partial class FooEntityObject 
{ 
    EntityCollection<Bar> Bars{get;set;} 
} 
2

Gần đây, tôi đã viết một bài đăng toàn diện về điều này: Persistence Ignorance in ADO.NET Entity Framework. Bạn có thể muốn xem xét EFPocoAdapter. Điều đó chỉ thực hiện điều này và cuối cùng nó sẽ không được chấp nhận vào EF v2.

Đối với những gì đáng giá, tôi đang sử dụng EFPocoAdapater và nó hoạt động tốt cho tôi.

2

Chúng tôi đã thực hiện chính xác điều tương tự cho LINQ to SQL. Tôi nhận được xung quanh vấn đề bộ sưu tập bằng cách viết một lớp học mà kết thúc tốt đẹp một IList và phôi đến và từ các loại chính xác theo yêu cầu. Có vẻ như thế này:

public class ListWrapper<TSource, TTarget> : IList<TTarget> 
    where TTarget : class 
    where TSource : class, TTarget 
{ 
    private IList<TSource> internalList; 

    public ListWrapper(IList<TSource> internalList) 
    { 
     this.internalList = internalList; 
    } 

    public void Add(TTarget item) 
    { 
     internalList.Add((TSource)item); 
    } 

    public IEnumerator<TTarget> GetEnumerator() 
    { 
     return new EnumeratorWrapper<TSource, TTarget>(internalList.GetEnumerator()); 
    } 

    // and all the other IList members 
} 

Đếm viênKết thúc tương tự như trình duyệt IE và thực hiện quá trình truyền. Trong LINQ to SQL các lớp học phần chúng ta tiếp xúc với các tài sản như thế này:

public IList<ICustomer> Foos 
{ 
    get 
    { 
     return new ListWrapper<Foo, IFoo>(this.Foos_internal); 
    } 
} 

Mọi thay đổi vào danh sách tiếp xúc sẽ được thực hiện trên EntitySet nội bộ để họ ở lại đồng bộ.

Điều này hoạt động tốt nhưng cảm giác của tôi là toàn bộ cách tiếp cận này gặp nhiều rắc rối hơn giá trị của nó, tôi là một fan NHibernate lớn và là người tin tưởng mạnh mẽ trong P.I. nhưng chúng tôi đã nỗ lực rất nhiều để làm điều này và chưa thực sự thấy được bất kỳ lợi thế nào. Chúng tôi sử dụng mẫu kho lưu trữ để trừu tượng đi truy cập DataContext thực tế mà tôi sẽ nói là phần quan trọng của việc tách chính chúng ta khỏi LINQ to SQL.

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