问题描述
EntityFramework可以支持EAV模型吗?这是可行的方案还是噩梦?我想在系统上使用EAV模型,并且希望尽可能使用EF,但是我担心这两种理念存在冲突。
Can EntityFramework support an EAV model? Is this a workable scenario, or a nightmare? I want to use an EAV model for a system, and I'd like to embrace EF if possible, but I'm concerned that these two philosophies are in conflict.
推荐答案
这取决于您期望如何在应用程序中使用EAV。 EF可用于映射以下内容:
It depends how do you expect to use EAV in the application. EF can be used to map this:
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-to可以保留并查询这些内容-实体。现在,您可以通过定义助手属性来使您的实体可用(只能在您的应用程序中使用,而不能用于持久性或查询)。这些帮助程序属性只能用于实体类型始终存在的众所周知的属性-必须仍然在集合中访问可选属性:
This is what can be persisted and what can be queried by Linq-to-entities. Now you can make your entity usable by defining helper properties (can be used only in your application but not by persistance or querying). These helper properties can be used only for well known attributes which will always exists for entity type - optional attributes must be still accessed in collection:
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();
}
}
}
这不是很好,因为转化和馆藏搜索。如果您多次访问数据,它们将被多次执行。
This is not very nice because of conversions and collection searching. If you access data multiple times they will be executed multiple times.
我没有尝试过,但是我认为可以通过每个实体实现类似的接口来避免这种情况:
I didn't tried it but I think this can be avoided by implementing a similar interface by each entity:
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();
}
现在您将处理 ObjectMaterialized $ c $
获取实现 ObjectContext
上的c>和 SavingChanges
事件。如果实现对象在第二个处理程序中实现 IEavEntity
,则在第一个处理程序中将执行 Initialize
。 c> ObjectStateManager IEavEntity
的所有更新或插入的实体,您将执行 Finalize
。像这样的东西:
Now you will handle ObjectMaterialized
and SavingChanges
events on ObjectContext
. In the first handler you will execute Initialize
if materialized object implements IEavEntity
in the second handler you will iterate ObjectStateManager
to get all updated or inserted entities implementing IEavEntity
and you will execute Finalize
. Something like:
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();
}
}
}
}
}
这篇关于EntityFramework可以支持EAV模型吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!