Entity Framework Code First Left Join

断了今生、忘了曾经 提交于 2019-12-06 08:52:43

问题


I've created a simple DB in EF code first but appear to have hit a problem.

What I would like to do is, query the DBContext to retrieve a custom object CheckedTag that would have all of the available tags and a boolean field of checked.

Code First abstracts the Many-To-Many table and I can't seem to find the correct query.

I've tried

            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 
                         };

and scoured the net for a few hours now.

If the articleId were to be 0, it would retrieve all of the tags and checked would be set to false, if the articleId was for an existing article all of the tags would be returned and the checked tags would be set to true.

Can anyone suggest the query I need to use to retrieve to achieve this result?


回答1:


if I understand correctly, you would like to get, for a particular article (having as id 'articleId), the list of all the tags (not just those it has), and put a "Checked" to true if it does have it, false otherwise. If so, here's the query I would suggest:

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

Hope this helps :)

Edit: replaced "Contains" with "Any". Thanks @Yakimych.




回答2:


I would suggest one slight improvement on AbdouMoumen's answer. (tested in .Net 4 with EF 4)

I checked with SQL profiler and the statement 'Checked = t.Articles.Any(...)' while it gives the correct results it produces slightly inefficient SQL code.

(NOTE: my code has different entity names but the exact same scenario)

produces this code:

    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]

I tested by changing it to 'Checked = (t.Articles.Any(...)) ? true : false' the resulting data is the same with a slightly better SQL code. this produces:

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]

p.s. perhaps this should be a comment but I don't yet have privilege to comment, so if I'm abusing this site please advise on the correct method I should follow.



来源:https://stackoverflow.com/questions/5729280/entity-framework-code-first-left-join

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!