2009-03-29 5 views
9

Entity Framework'de Foo var. Ama iş mantığımın IFoo'u bilmesi için IFoo'dan miras almamı sağlayarak Entity Framework'ü uzaklaştırıyorum.Entity Framework'ü varlığımdan soyutlayabilir miyim?

sorun FooBar birimlerin bir koleksiyona sahip olmasıdır. Ve bu koleksiyon EntityCollection<Bar> tipindedir.

Bu koleksiyonu IFoo numaralı telefona koyarsam, IFoo'u Entity Framework'e bağımlı hale getiriyorum. Bu yüzden onu ICollection<IBar> olarak koymayı düşündüm, ancak bu (doğal olarak) derlenmiyor.

Düşünebildiğim tek çözüm, Entity Framework tasarımcısı tarafından oluşturulan Foo somut örneğine gitmek ve buradaki koleksiyonu EntityCollection<Bar> ile ICollection<IBar> arasında değiştirmek. Ama Entity Çerçevesinde "sahnelerin ardında" yer alacağı etkilerin düşüncesinden korktum.

hala onları uygulamak EF varlıkları olarak Foo ve Bar korurken bağımsız Varlık Framework IFoo ve IBar tanımlamak benim için herhangi bir yolu var mı? IFoo ve IBar Do'yu yapmak, amacım olduğu bu bağımsızlığı elde edemezsek, mantıklı olabilir mi?

+0

IFoos ve IBars'ın Foos ve Barlar yerine tam olarak olmasını istediğiniz sebep nedir? – Inferis

+0

Kalıcılık cehaletini hedefliyorum. Aşağıdaki kabul edilen cevaba bakınız. – urig

cevap

8

kastediyorsun genel kavram, "kalıcılık cehalet" (PI) 'dir.

Her durumda, hazırda ve NHibernate doğal PI desteklemek, ancak Microsoft'un Entity Framework ilk sürümü yok.MS, bunun için çok fazla karışma yakaladı ve PI, muhtemelen, bir sonraki sürüm için en çok tartışılan özelliktir (her ne zaman).

Arabirimlerle ne yapmaya çalıştığınız konusunda, Barlar koleksiyonunun alındıktan sonra değiştirilmesi mi gerekiyor? Cevap evet ise, kolay bir cevap yoktur. ICollection<T> bir Add yöntemine sahip olduğundan, kovaryans bile size yardımcı olamaz.

Koleksiyon salt okunursa, IEnumerable<IBar> olarak göstermeyi düşünebilirsiniz. Enumerable.Cast yöntemi bunu oldukça kullanışlı hale getirir.

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

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

Ayrıca, EF destek kalıcılık cehalet akım versiyonunu yapmak için at least one effort biliyorum.

+0

Neden değişiklikler yapılamaz? AttachTo nesneyi bağlamadan sonra değişiklik yaptıktan sonra bağlayabilir. – aleemb

+0

EF 4 bunu mu yapıyor? – BigJoe714

2

Java geliştiriciyim, bu nedenle Entity Framework ile ilgili herhangi bir otoriteye yorum yapamıyorum. Hibernate gibi ORM çözümlerinin ortak soyut sınıflara, arabirimlere veya bayt kodunda değişiklik yapmaya gerek kalmadan POJO'nun kalıcılığını sağladığını söyleyebilirim. Foo ve Bar'ınız için özel toplama dersleri kullanmak zorunda kalmadan 1: m gibi ilişkileri ele alır.

Özel sos, haritalandırma yapılandırmasıyla dışsallaştırılır ve Hazırda bekletme işlemi gerçekleştirilir. POCO kalıcılık: Ben Entity Framework hakkında okuyun

biraz aynı amacı ile bir ORM çözüm önerir. Arayüzlerden bahsetmedim. Örneklerinden onlara olan ihtiyacı göremiyorum çünkü çok soyut.

ben hazırda yapıyor biliyorum, çünkü o arayüzler başvurmak zorunda kalmadan iş nesneleri ve kalıcılık katmanı arasındaki bağımsızlık elde etmenin mümkün olduğunu çıkarım ediyorum. Spring'in JDBC çözümünün de bunu başardığını söyleyebilirim, çünkü ortak arayüzlere gerek yoktur. Bir sorgudan ve bir nesneden veriyi fethetmek için bir RowMapper yapısı kullanırlar.

ben Entity Framework ile nasıl yapılacağını tam olarak size tavsiyelerde isterdim ama belki bu yapılabilir bilerek kalbini götüreceğiz.

+0

Detaylı yanıt için teşekkürler. Geçmişte, NHibernate, Java'nın Hazırda Bekletme'nin .net sürümünde olumlu bir deneyim yaşadım. EF konusunda uzman değilim, ancak bir XML dosyasında dışa aktarılmak yerine eşlemenin özellik temelli olduğunu anlıyorum. İşte bu yüzden bir arayüz üzerinden soyutlamam gerekiyor. Sanırım;) – urig

+0

Belki de haklısınız. Bir Google makalesiyle ilgili kısa bir süre içinde hiçbir kanıt görmedim. Üzgünüm daha fazla yardımcı değilim. – duffymo

2

autogenerated EF nesnelerden mantık ve kuralları ayırmak için kısmi sınıfını kullanın. Aşağıdaki örnekte FooEntityObject sınıfı, kısmi anahtar kelimeyi kullanarak ikiye bölünmüştür. Bu tekniği daha önce EF ve LINQ SQL ile kullanmıştım. Kısmi sınıflar ayrı dosyalarda saklanabilir, böylece EF nesnesini yeniden düzenlerseniz özel kodunuz tekrar yazılmaz. Bu genellikle varlıkları tüketir kodu yerine kuruluşlara doğrudan kendileri uygular rağmen

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

Son zamanlarda bu konuyla ilgili kapsamlı bir yazı yazdım: Persistence Ignorance in ADO.NET Entity Framework. EFPocoAdapter'e bakmak isteyebilirsiniz. Bu sadece bunu yapar ve sonuçta EF v2'ye geçer.

Değeri için EFPocoAdapater kullanıyorum ve benim için iyi çalışıyor.

2

LINQ to SQL için tam olarak aynı şeyi yapıyoruz. Koleksiyon sorunu etrafında, bir IList'u saran ve gerektiğinde doğru türden ve aşağıdan bir sınıf yazarak bir sınıf yazdım. Bu biraz şuna benzer:

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 
} 

EnumeratorWrapper benzer bir IEnumerator sarar ve casting gerçekleştirir. maruz listeye

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

tüm değişiklikler iç EntitySet üzerinde yapılacaktır onlar senkronize edilir, böylece: LINQ olarak böyle özelliği göstermiyor kısmi sınıfları SQL.

Bu, yeterince iyi çalışır, ancak benim bu yaklaşımın değerinden daha büyük bir sorun olduğu hissine kapıldım, büyük bir NHibernate hayranıyım ve P.I. ama bunu yapmak için çok fazla çaba harcadık ve gerçekten hiçbir avantaj görmedik. Kendimizi LINQ'dan SQL'e ayırmanın anahtar kısmı diyebileceğim gerçek DataContext erişimini soyutlamak için depo desenini kullanıyoruz.