如何使用Entity Framework 4从多语言数据库中建模POCO对象?

时间:2010-12-24 20:18:38

标签: c# entity-framework entity-framework-4 linq-to-entities multilingual

我正在从头开始构建一个新项目。 我创建了一个db,我一直应用了一个db结构,我用一个简短的不言自明的例子来解释:

表项目 - > (Id,Name) - >包含一般信息

表项目信息 - > (Item_Id,Language,Description) - >包含语言相关信息。

Id和Item_Id与外键关系连接。

我的想法是以一种最终只使用通过实体框架填充的单个POCO对象“Item”的方式对其进行建模。此对象仅包含公共属性:Id,Name和Description。 使用此对象将隐藏语言,对象本身应负责根据包含该语言的全局变量提供正确的描述。

我已经尝试了几种方法来做到这一点并且总是遇到问题,因为实体框架不允许这种情况。我总是必须检索所有语言的信息,而不仅仅是当前语言或使用2个不同的查询。

所以最后我开始使用的解决方案是让T4模板同时创建Item和ItemInfo,然后手动添加类似于此的代码:

public partial class Item
{
    private ItemInfo _itemInfo = null;
    private ItemInfo itemInfo
    {
        get
        {
            if (_itemInfo == null) _itemInfo = ItemInfoes.Single(p => p.Language == GlobalContext.Language);
            return _itemInfo;
        }
    }
    public Description 
    {
        get { return itemInfo.Description; } 
        set { itemInfo.Description = value;}
    }
}

使用此代码,我将ItemInfo中的其他属性添加到Item,并根据我的要求选择了正确的语言。 你认为这是一个很好的解决方案吗?你会如何解决这个问题?

但是,运行sql profiler我可以看到2个不同的sql查询用于填充Item对象,一个查询Item表,另一个查询ItemInfo。

使用在2个表之间进行连接的单个查询可以实现相同的方案吗? (我担心长期性能受到影响,而且如果没有ORM,我也会这样做。)

任何建议都会受到欢迎,我有多年的编程经验,但我是Entity Framework和ORMs的新手。

请帮忙。

3 个答案:

答案 0 :(得分:6)

您没有展示如何获取Item个对象,但通常我没有看到在一个查询中获取所有内容时出现问题。你有几个选择 你可以做一个投影(但不能做到映射的实体 - 在这个例子中我投射到一个匿名对象上):

context.
Items.
Select(item => new 
               {
                   Id = item.Id,
                   Name = item.Name,
                   Description = item.
                                 ItemInfo.
                                 Where(info => info.Language == YourGlobalLang).
                                 Select(info => info.Description).
                                 FirstOrDefault()
               };

(已将其编辑为使用FirstOrDefault而不是Single - 请参阅@Craig Stuntz的评论讨论)

这将返回所有Items的列表 - 您可以添加Where子句进行过滤。

或者您可以反过来获取它(从ItemInfo开始):

ItemInfo itemInfo = context.
                    ItemInfoes.
                    Include(info => info.Item).
                    SingleOrDefault(info => info.Language == YourGlobalLang && 
                                            info.Item.Id == itemIdToFetch);

之后,您可以访问项目对象本身:

Item item = itemInfo.Item;

答案 1 :(得分:1)

我认为这是一种合理的方法。此外,我不会担心两个简单选择的性能问题。如果将来发现问题,您可以将其更改为视图,例如。

答案 2 :(得分:0)

您可以尝试动态添加where子句。 或者据说直接使用linq to sql。

How to append a where clause to an Entity Framework ObjectSet

Add the where clause dynamically in Entity Framework