【问题标题】:Entity Framework Code First Left Join实体框架代码先左连接
【发布时间】:2011-11-22 02:29:03
【问题描述】:

我首先在 EF 代码中创建了一个简单的数据库,但似乎遇到了问题。

我想要做的是,查询 DBContext 以检索自定义对象 CheckedTag,该对象将具有所有可用标签和选中的布尔字段。

Code First 抽象了多对多表,我似乎找不到正确的查询。

我试过了

            var qry = from t in Db.Tags
                  from a in Db.Articles
                  where(a.Id == articleId) 
                  select new CheckedTag 
                         { 
                             Id = t.Id, 
                             Name = t.Name, 
                             PermanentUrl = t.PermanentUrl, 
                             Checked = t.Id == null ? false : true 
                         };

现在在网上搜索了几个小时。

如果 articleId 为 0,它将检索所有标签,并且检查将设置为 false,如果 articleId 用于现有文章,则将返回所有标签并将检查标签设置为 true .

谁能建议我需要用来检索以实现此结果的查询?

【问题讨论】:

    标签: entity-framework linq-to-entities many-to-many left-join ef-code-first


    【解决方案1】:

    如果我理解正确,您希望获取特定文章(具有 id 'articleId)的所有标签列表(不仅仅是它拥有的标签),如果是,则将“已检查”设置为 true确实有,否则为假。如果是这样,这是我建议的查询:

    var checkedTags= from t in Db.Tags
                     select new CheckedTag
                            {
                                Id = t.id,
                                Name = t.name,
                                PermanentUrl = t.PermanentUrl,
                                Checked = t.Articles.Any(a => a.Id == articleId)
                            };
    

    希望这会有所帮助:)

    编辑:将“包含”替换为“任何”。谢谢@Yakimych。

    【讨论】:

    • 你在正确的轨道上,但使用Any而不是Contains
    • 感谢 Abdou 和 Yakimych,你为我解决了一个头痛问题 :)
    【解决方案2】:

    我建议对 AbdouMoumen 的回答稍作改进。 (在 .Net 4 和 EF 4 中测试)

    我检查了 SQL 分析器和语句“Checked = t.Articles.Any(...)”,虽然它给出了正确的结果,但它产生的 SQL 代码效率略低。

    (注意:我的代码有不同的实体名称,但场景完全相同)

    产生这个代码:

        CASE WHEN ( EXISTS (SELECT 
        1 AS [C1]
        FROM [dbo].[LocationFeatures] AS [Extent2]
        WHERE ([Extent1].[FeatureID] = [Extent2].[FeatureID]) AND (1 = [Extent2].[LocationID])
    )) THEN cast(1 as bit) WHEN ( NOT EXISTS (SELECT 
        1 AS [C1]
        FROM [dbo].[LocationFeatures] AS [Extent3]
        WHERE ([Extent1].[FeatureID] = [Extent3].[FeatureID]) AND (1 = [Extent3].[LocationID])
    )) THEN cast(0 as bit) END AS [C1]
    

    我通过将其更改为 'Checked = (t.Articles.Any(...)) 进行了测试? true : false' 结果数据与稍好一点的 SQL 代码相同。 这会产生:

    CASE WHEN ( EXISTS (SELECT 
        1 AS [C1]
        FROM [dbo].[LocationFeatures] AS [Extent2]
        WHERE ([Extent1].[FeatureID] = [Extent2].[FeatureID]) AND (1 = [Extent2].[LocationID])
    )) THEN cast(1 as bit) ELSE cast(0 as bit) END AS [C1]
    

    附言也许这应该是一个评论,但我还没有评论的特权,所以如果我滥用这个网站,请告诉我应该遵循的正确方法。

    【讨论】:

      猜你喜欢
      • 2015-04-09
      • 2012-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多