使用实体框架继承的瓶颈

时间:2011-07-05 17:33:26

标签: entity-framework entity-framework-4

首先是我的实体

Entities

问题我想要一个包含所有故事标题及其类型的页面

有三个故事LongStoryCoOpStoryGenericStory

通用故事与StoryType关于通用故事的类型

相关联

我有两个问题

首先,当我想检查故事是LongStory还是CoOpStory时,我必须获取所有实体并检查实体类型是否为LongStory然后做某事,我不要我不知道如何检索一些数据[只有标题]并检查类型

我的第二个问题就像我说我想要一个包含所有故事标题及其类型的页面我不知道怎么做而不进行大量查询,我无法加入{{ 1}}表因为它必须与StoryType相关联,所以我首先得到的所有故事然后为每个GenericStory做一个额外的查询以获得类型

3 个答案:

答案 0 :(得分:4)

您正在查看OfTypeConcat扩展方法。

要只获取LongStory实例,您只需要调用:

var longStories = context.Stories.OfType<LongStory>().ToList();

为了获得更大的查询,它有点复杂。你可以尝试:

var allStories = context.Stories
                        .OfType<GenericStory>()
                        .Include("StoryType") // I'm not sure how this works with concat
                        .Concat(
                             context.Stories.OfType<LongStory>.Concat(         
                                  context.Stories.OfType<CoOpStory>()));

或者你可以进行投射:

var allStories = context.Stories
                        .OfType<GenericStory>()
                        .Select(s => new { s.Title, s.StoryType.Name })
                        .Concat(
                             context.Stories
                                    .OfType<LongStory>
                                    .Select(s => new { s.Title, "LongStory" })
                                    .Concat(         
                                        context.Stories
                                               .OfType<CoOpStory>()
                                               .Select(s => new { s.Title, Type })));

答案 1 :(得分:3)

Ladislav的回答是针对你的第二个问题。这是第一个问题的可能解决方案。

据我所知,您无法直接查询投影中的类型(例如,使用GetType()将无法在LINQ to Entities中使用)。但是,如果您只想查询故事的标题和类型,则以下内容将起作用:

var stories = context.Stories
    .Select(s => new
    {
        Title = s.Title,
        Type = (s is LongStory) ? "LongStory" :
               (s is CoOpStory) ? "CoOpStory" :
               (s is GenericStory) ? "GenericStory" :
               (s is Story) ? "Story" : // forget this if Story is abstract
               "Unknown"
    }).ToList();

您将获得一个匿名对象列表,其中Type属性将此类型表示为此查询中的自定义字符串。

不太好,因为每次向层次结构添加新类时都必须更改此查询。顺序也很重要(大多数派生类必须首先在Type属性的表达式中)。但我不知道另一种方式。

答案 2 :(得分:-1)

你尝试过这样的事吗?

context.Stories.OfType<LongStory>.Where(...).Cast<Story>()
 .Union(context.Stories.OfType<GenericStory>.‌​Where(...).Include(s => s.StoryType).Cast<Story>())
 .Union(context.Stories.OfType<CoOpStory>.Where(...).Cast<Story>());