Reputation: 4898
How can I write the following SQL in LINQ to Entities?
SELECT r.rolename,
( CASE
WHEN ur.username IS NULL THEN 0
ELSE 1
END ) AS isinrole
FROM bgt.roles r
LEFT OUTER JOIN bgt.usersinroles ur
ON ur.rolename = r.rolename
AND ur.username = 'ADMIN'
Upvotes: 3
Views: 4248
Reputation: 1111
Extension method for Left join (linq to entities):
public static class DbSetExtensions
{
public static IQueryable<TResult2> LeftJoin<TOuter, TInner, TKey, TResult2>(
this IQueryable<TOuter> outerList,
IEnumerable<TInner> innerList,
Expression<Func<TOuter, TKey>> outerKeySelector,
Expression<Func<TInner, TKey>> innerKeySelector,
Expression<Func<LeftJoinTemp<TOuter, TInner>, TInner, TResult2>> resultSelector2)
{
// (tr, historicPrices) => new { tr, historicPrices }
Expression<Func<TOuter, IEnumerable<TInner>, LeftJoinTemp<TOuter, TInner>>> myResultSelector1
= (tr, historicPrices) => new LeftJoinTemp<TOuter, TInner> { outer = tr, inners = historicPrices };
// e => e.historicPrices.DefaultIfEmpty()
Expression<Func<LeftJoinTemp<TOuter, TInner>, IEnumerable<TInner>>> myCollectionSelector
= e => e.inners.DefaultIfEmpty();
//var a = outerList.GroupJoin(innerList, outerKeySelector, innerKeySelector, resultSelector1);
var a = outerList.GroupJoin(innerList, outerKeySelector, innerKeySelector, myResultSelector1);
//return a.SelectMany(collectionSelector, resultSelector2);
var b = a.SelectMany(myCollectionSelector, resultSelector2);
return b;
}
}
public class LeftJoinTemp<TOuter, TInner>
{
public TOuter outer;
public IEnumerable<TInner> inners;
}
example calling, left join of Transaction and HistoricPrice, for transaction you have to write parent.outer
.LeftJoin(db.HistoricPrices,
transaction => new { transaction.InstrumentId, DateId = transaction.Date2Id },
historicPrice => new { historicPrice.InstrumentId, historicPrice.DateId },
(parent, historicPrice) => new
{
parent.outer.Id,
parent.outer.OpeningDate,
parent.outer.InstrumentName,
historicPrice.DateId,
historicPrice.InstrumentId
})
Upvotes: 0
Reputation: 4898
This worked for me. Thanks for all the suggestions.
var query =
from r in Roles
from ur in UsersInRoles
.Where(v => v.Rolename == r.Rolename && v.Username == "ADMIN")
.DefaultIfEmpty()
select new { Rolename = r.Rolename, IsInRole = (ur.Username != null) };
The generated SQL is as follows
SELECT
1 AS [C1],
[Extent1].[Rolename] AS [Rolename],
CASE WHEN ([Extent2].[Username] IS NOT NULL) THEN cast(1 as bit) WHEN ([Extent2].[Username] IS NULL) THEN cast(0 as bit) END AS [C2]
FROM [bgt].[Roles] AS [Extent1]
LEFT OUTER JOIN [bgt].[UsersInRoles] AS [Extent2] ON ([Extent2].[Rolename] = [Extent1].[Rolename]) AND ('ADMIN' = [Extent2].[Username])
Upvotes: 3
Reputation: 245056
I would do it like this:
from role in db.Roles
let isInRole = role.UsersInRoles.Any(u => u.UserName == "ADMIN")
select new { role.RoleName, isInRole }
Althought the generated SQL is not as nice as yours.
Upvotes: 2