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
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();
}
}
}
}
}