开发者

Entity Framework Code First Left Join

Entity Framework Code First Left Join

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 o开发者_JS百科f 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?


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.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜