2011-03-31 11 views
6

EntityFramework bir EAV modelini destekleyebilir mi? Bu işe yarayan bir senaryo mu, yoksa kabus mu? Bir sistem için bir EAV modeli kullanmak istiyorum ve eğer mümkünse EF'yi kucaklamak istiyorum ama bu iki felsefenin çatıştığından endişe ediyorum.EntityFramework bir EAV modelini destekleyebilir mi?

cevap

9

Uygulamada EAV'yi kullanmayı nasıl beklersiniz. EF bu haritaya kullanılabilir:

public partial class Entity 
{ 
    // Key 
    public virtual int Id { get; set; } 
    // Other common properties 

    // Attributes 
    public virtual ICollection<EavAttriubte> Attributes { get; set; } 
} 

// The simplest implementation 
public class EavAttribute 
{ 
    // Key 
    public virtual int Id { get; set; } 
    public virtual string Name { get; set; } 
    public virtual string Value { get; set; } 
} 

Bu neyi kalıcı olabilir ve hangi Linq kuruluşlar tarafından sorgulanabilir edilir. Artık, yardımcı özelliklerini tanımlayarak varlığınızı kullanılabilir hale getirebilirsiniz (yalnızca uygulamanızda kullanılabilir, ancak kalıcı veya sorgulama yoluyla kullanılamaz).

public partial class Entity 
{ 
    // Just example without error handling 
    public decimal Price 
    { 
     get 
     { 
      return Int32.Parse(Attributes.Single(a => a.Name == "Price")); 
     } 
     set 
     { 
      Attributes.Single(a => a.Name == "Price").Value = value.ToString(); 
     } 
    } 
} 

Bunun nedeni dönüşümleri ve toplama arama çok güzel değil: isteğe bağlı ayrıntılar halen koleksiyonunda erişilebilir olmalıdır - Bu yardımcı özellikler olacak hep varlık türü için var olan iyi bilinen özellikler için sadece kullanılabilir. Verilere birden çok kez erişirseniz, bunlar birden çok kez çalıştırılacaktır.

Denedim olmadı ama bu her varlık tarafından benzer bir arabirim uygulama önlenebilir düşünüyorum:

public interface IEavEntity 
{ 
    // loads attribute values from Attributes collection to local fields 
    // => conversion will be done only once 
    void Initialize(); 
    // saves local values back to Attributes collection 
    void Finalize(); 
} 

Şimdi ObjectContext üzerinde ObjectMaterialized ve SavingChanges olayları işleyecektir. İlk işleyicide, IEavEntity maddesini uyguladıysanız, IEavEntity maddesini uyguladıysanız, IEavEntity'u uyguladıysanız, IEavEntity'u uygulayan tüm güncel veya eklenmiş varlıkları almak için 'u çalıştıracaksınız ve Finalize'u yürütün. Bir şey gibi:

public void OnMaterialized(object sender, ObjectMaterializedEventArgs e) 
{ 
    var entity = e.Entity as IEavEntity; 
    if (entity != null) 
    { 
     entity.Initialize(); 
    } 
} 

public void SavingChanges(object sender, EventArgs e) 
{ 
    var context = sender as ObjectContext; 
    if (context != null) 
    { 
     foreach (var entry in context.ObjectStateManager.GetObjectStateEntries(
      EntityState.Added | EntityState.Modified)) 
     { 
      if (!entry.IsRelationship) 
      { 
       var entity = entry.Entity as IEavEntity; 
       if (entity != null) 
       { 
        entity.Finalize(); 
       } 
      } 
     } 
    } 
}