2011-07-05 146 views
4

所以首先我的实体瓶颈使用实体框架继承

Entities

我想和所有的故事标题页面中的问题及其类型

有三个故事LongStoryCoOpStoryGenericStory

通用故事与StoryType相关联,用于通用故事的类型

我有两个问题

第一当我要检查,如果这个故事是LongStoryCoOpStory我已经把所有的实体,并检查实体类型,如果它是LongStory然后做一些事情,我不知道如何检索一些数据[只有标题],并检查类型

我的第二个问题,就像我说我想要一个页面,所有的故事标题和他们的类型我不知道如何做,而不做很多的查询,我无法加入到StoryType表中,因为它必须与GenericStory关联,所以我首先获取所有故事,然后为每个查询做额外的查询GenericStory即可获得类型

回答

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 }))); 
+0

大声笑,我刚刚停止写作:)是'allStories'查询实际上是三往返回数据库?我也考虑过'Concat',但参数是'IEnumerable',而不是'IQueryable'。我不确定我们是否会得到三个roundrips。上下文。历史。OfType .Concat(context.Stories.OfType ())''可能可能压缩到'context.Stories.Where(s =>!(s是GenericStory))'中。 – Slauma

+0

'Concat'被简单地转换为'UNION ALL'和'Union'到'UNION'。如果没有,则无法在linq-to-entities中进行联合。这压缩很酷:)我想过如何避免两个连接的方式,但这并没有出现在我的脑海。 –

+0

很高兴知道'Concat'如何翻译!最后,我发现这个问题的第一部分有些难看(但工作)。我想知道这是否不可能以更简单的方式进行。 – Slauma

3

拉吉斯拉夫的答案是你的第二个问题。这是您的第一个问题的可能解决方案。

据我可以看到,你不能直接查询投影中的类型(使用GetType()例如不会在LINQ to Entities中工作)。但是,下面的工作,如果你想例如只查询标题和故事的类型:其中Type属性表示类型在此查询您的自定义字符串

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属性的表达式中)。但我不知道另一种方式。

+0

抱歉不能标记这两个答案,但真的很好的信息,谢谢 –

-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>()); 
+2

这看起来非常好,并解决了连接不同类型集合的问题。不幸的是,EF抱怨'Include'路径无效,'StoryType'不是'Story'类型的声明属性,我只是测试了它。在'OfType ()'实际得到应用之前,'Include'似乎应用于'DbSet '。 – Slauma