2011-03-31 4 views
6

EntityFramework가 EAV 모델을 지원할 수 있습니까? 이것은 실행 가능한 시나리오입니까, 아니면 악몽입니까? 나는 시스템을 위해 EAV 모델을 사용하고 싶다. 가능한 한 EF를 포용하고 싶지만, 나는이 두 철학이 충돌하고 있다고 우려하고있다.EntityFramework는 EAV 모델을 지원할 수 있습니까?

답변

9

응용 프로그램에서 EAV를 사용하는 방법은 어떻게 달라질까요? EF는이지도하는 데 사용할 수 있습니다

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

가 이것은 무엇을 지속 할 수 있고 무엇을하는 것은 Linq에 - 투 - 엔티티 조회 할 수있다. 이제 도우미 속성을 정의하여 엔티티를 사용할 수있게 만들 수 있습니다 (응용 프로그램에서만 사용할 수 있지만 지속성이나 쿼리에서는 사용할 수 없음).

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

이 때문에 변환 및 수집 검색의 아주 좋은되지 않습니다 : 선택적 속성이 여전히 모음에 액세스해야합니다 -이 도우미 속성는 항상 개체 유형을 위해 존재 잘 알려진 속성에 대해서만 사용할 수 있습니다. 데이터에 여러 번 액세스하면 여러 번 실행됩니다.

나는 그것을 시도하지 않았다 그러나 나는이 각 엔티티에 의해 유사한 인터페이스를 구현하여 방지 할 수 있다고 생각 :

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

지금 당신이 ObjectContextObjectMaterializedSavingChanges 이벤트를 처리합니다. 첫번째 핸들러에서 구체화 된 오브젝트가 IEavEntity을 두 번째 핸들러에 구현하는 경우 Initialize을 실행하면 ObjectStateManager을 반복하여 IEavEntity을 구현하는 모든 갱신 또는 삽입 된 엔티티를 가져오고 Finalize을 실행합니다. 다음과 같음 :

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(); 
       } 
      } 
     } 
    } 
} 
관련 문제