EAV - 使用Linq为实体获取价值

时间:2012-12-04 17:33:45

标签: linq entity-framework linq-to-entities entity-attribute-value

在像这样的数据模型(http://alanstorm.com/2009/img/magento-book/eav.png)中,我想使用Linq到SQL从EAV_Attribute获取值。

enter image description here

假设EAV_Attribute只存在于一个继承表(varchar,decimal,int等)中,如何在linq查询中获取它?

我知道我可以使用继承,但我想在SQL数据库端执行它...

考虑到元素有不同的类型,是否可以在Linq中进行一种Coalesce?

2 个答案:

答案 0 :(得分:0)

EAV和linq不是幸福的婚姻。我认为您最好的方法是在eav_attribute中创建一个未映射的属性,该属性可以从其类型属性子元素中解析值(如object)。使用实体框架,您将无法在表达式中使用此属性(即不在WhereSelect中),您必须先转换为IEnumerable才能访问它。 (Linq-to-sql可能允许它,因为它可以切换到引擎盖下面的linq-to-objects)。

另一种选择是创建一个类型为sql_variant的计算列,该列执行相同的操作,但现在使用t-sql代码。但是...... EF没有支持sql_variant。您必须使用some trickery来阅读它。

这是阅读部分。

对于设置/修改/删除值,我看不到任何快捷方式。您只需将父对象和子对象作为任何对象图处理对象。在sql server中,您不能使用级联删除,因为它只能为一个外键定义。 (This可以解决这个问题,但我从未尝试过。)

所以,不是真的好消息,我害怕。也许很高兴知道在一个项目中我也使用具有不可避免的EAV部分的数据库。我们也用EF做它,但它不是没有摩擦。

答案 1 :(得分:0)

首先,我建议使用TPH而不是TPT用于EAV表。 (一个表有多个可空值列(每个类型一个)+鉴别器与每个类型一个表。)

无论哪种方式,如果你将值实体建模为一个抽象类(包含两个ID),每个值数据类型都有一个继承实体,它会添加value属性,那么你的LINQ应该是这样的:

var valueEntity = context.ProductAttributes.Where(pa =>
        pa.ProductId == selectedProductId
        && pa.AttributeTypeId == selectedAttributeTypeId)
    .SingleOrDefault() as ProductAttributeOfDouble;

if valueEntity != null
    return valueEntity.Value;

return null;

实体类型为:Product,AttributeType,ProductAttribute,ProductAttributeOfDouble,... ProductAttributeOfString。