LINQ to SQL query using "NOT IN" - sql

Can LINQ to SQL query using NOT IN?
e.g., SELECT au_lname, state FROM authors WHERE state NOT IN ('CA', 'IN', 'MD')

List<string> states = new List<string> { "CA", "IN", "MD" };
var q = from a in authors
where !states.Contains(a.state)
select new { a.au_lname, a.state };
or
var q = authors.Where( a => !states.Contains( a.state ) )
.Select( a => new { a.au_lname, a.state } );

You can do it with Contains:
var states = new[] {"CA", "IN", "MD"};
var query = db.Authors.Where(x => !states.Contains(x.state));

here's an example:
NorthwindDataContext dc = new NorthwindDataContext();
dc.Log = Console.Out;
var query =
from c in dc.Customers
where !(from o in dc.Orders
select o.CustomerID)
.Contains(c.CustomerID)
select c;
foreach (var c in query) Console.WriteLine( c );

Yes!
Here's an example from code we already had written:
List<long> badUserIDs = new List { 10039309, 38300590, 500170561 };
BTDataContext dc = new BTDataContext();
var items = from u in dc.Users
where !badUserIDs.Contains(u.FbUserID)
select u;
The generated SQL turns out to be:
{SELECT [t0].[UserID], [t0].[FbUserID], [t0].[FbNetworkID], [t0].[Name],
FROM [dbo].[Users] AS [t0]
WHERE NOT ([t0].[FbUserID] IN (#p0, #p1, #p2))
}

Related

Entity Framework Linq to SQL expression containing LEFT JOIN

I'm attempting to translate some T-SQL to an Entity Framework Core lambda expression. It involves an inner join and a left joing with a where clause.
Here is the working SQL query:
SELECT
AspNetUsers.*, Exclusions.*
FROM
AspNetUsers
JOIN Exclusions ON
AspNetUsers.FirstName = Exclusions.FirstName
AND AspNetUsers.LastName = Exclusions.LastName
LEFT JOIN ExclusionsMatches ON
ExclusionsMatches.RowHash = Exclusions.RowHash
WHERE
ExclusionsMatches.MatchIgnoredByUserId IS NULL
Which I have thus far translated into LINQ lambda as such:
var result = _db.Users
.Join(_db.Exclusions, usr => new { usr.FirstName, usr.LastName }, Exc => new { Exc.FirstName, Exc.LastName }, (usr, Exc) => new { usr, Exc })
.GroupJoin(_db.ExclusionsMatches, i => i.Exc.RowHash, x => x.RowHash, (i, ExcMatch) => new { User = i.usr, Exc = i.Exc, ExcMatch = ExcMatch })
.SelectMany(temp => temp.ExcMatch.DefaultIfEmpty(), (temp, p) => new { User = temp.User, Exc = temp.Exc, ExcMatch = temp.ExcMatch})
This seems to give me the desired query output, but I can't seem to figure out how to get the WHERE ExclusionsMatches.MatchIgnoredByUserId IS NULL clause translated.
Any thoughts on how the WHERE might be achieved? I'm also open to changing from lambda expression to linq query expression.
Thanks!
I believe using LINQ is more readable so I can provide an answer using LINQ as below.
from user in _db.Users
join excl in _db.Exclusions on new { usr.FirstName , usr.LastName} equals {excl.FirstName , excl.LastName}
join exclMtch in _db.ExclusionsMatches on excl.RowHash equals exclMtch.RowHash into grp
from itm in grp.DefaultIfEmpty()
where itm.MatchIgnoredByUserId == null
select new {
user,
excl
}
Otherwise, if you insist on using Lambda, first you have to select the field in your final selects and then add the needed where in the end of query.
var result = _db.Users
.Join(_db.Exclusions, usr => new { usr.FirstName, usr.LastName }, Exc => new { Exc.FirstName, Exc.LastName }, (usr, Exc) => new { usr, Exc })
.GroupJoin(_db.ExclusionsMatches, i => i.Exc.RowHash, x => x.RowHash, (i, ExcMatch) => new { User = i.usr, Exc = i.Exc, ExcMatch = ExcMatch MatchIgnoredByUserId = i.MatchIgnoredByUserId })
.SelectMany(temp => temp.ExcMatch.DefaultIfEmpty(), (temp, p) => new { User = temp.User, Exc = temp.Exc, ExcMatch = temp.ExcMatch, MatchIgnoredByUserId= temp.MatchIgnoredByUserId })
.Where(q => q.MatchIgnoredByUserId == null )
Do not forget to track your query in SQL Profiler :)

Convert sql to Lambda expression

Guy's I need a Lambda expression for this sql statement.
select GalleryId, Max(Bid)
from BidModels
where GalleryId in (select GalleryId from BidModels where UserId = (UserId))
group by GalleryId
I don't see why you need the subquery, given that you can just select all Bids where UserId = userid being passed in. With that in mind:
var userid = <whatever>;
var query = from b in BidModels
where b.UserId = userid
group by b.GalleryId into g
select new {Id = g.Key, MaxBid = g.Max(x => x.Bid)};
Here is how you can do it
var galleryIds = (bidModelses.Where(b => b.UserId == [YOURPARAMETER])
.Select(b => b.GalleryId));
var query = (bidModelses.Where(bm => galleryIds.Contains(bm.GalleryId))
.GroupBy(bm => bm.GalleryId)
.Select(gbm => new {gbm.Key, MaxBid = gbm.Max(p => p.BidId)}));
This seems to be the answer thanks for the help:
from b in BidModels
let MyGallery = from a in BidModels where a.UserId == (1) select new { a.GalleryId }
where MyGallery.Any()
group b.Bid by b.GalleryId into g
select new
{ Id = g.Key,
MaxBid = g.Max()
}

translating sql statement to linq

I have a working sql statement and want it as linq statement or linq methode chain.
My statement is:
SELECT T1.*
FROM (SELECT Col1, MAX(InsertDate) as Data
FROM Zugbewegungsdaten
GROUP BY Loknummer) as temp JOIN T1
ON (T1.Col1= temp.Col1
AND Zugbewegungsdaten.InsertDate= temp.Date)
WHERE Col3=1
ORDER BY Loknummer
Can anybody help me to translate it?
Edit after comment:
Ok, my result for the inner select:
var maxResult = (from data in context.T1
group data by data.Col1
into groups
select new
{
Train = groups.Key,
InsertDate= groups.Max( arg => arg.InsertDate)
}) ;
I tried the join like this:
var joinedResult = from data in context.T1
join gdata in maxResult on new
{
data.Col1,
data.InsertDate
}
equals new
{
gdata.Col1,
gdata.InsertDate
}
select data;
But i get a compiler error by the join that the typeargument are invalid.
In the case that the join works i whould use a where to filter the joinedResult.
var result = from data in joinedResult
where data.Col3 == true
select data;
After much more "try and error", I got this version it looks like it works.
var joinedResult = ( ( from data in context.T1
group data by data.Col1
into g
select new
{
Key= g.Key,
Date = g.Max( p => p.InsertDate)
} ) ).Join( context.T1,
temp => new
{
Key = temp.Key,
InsertDate = temp.Date
},
data => new
{
Key = data.Col1,
InsertDate = data.InsertDate
},
( temp,
data ) => new
{
temp,
data
} )
.Where( arg => arg.data.Col3)
.OrderBy( arg => arg.data.Col1)
.Select( arg => arg.data );
Could it be that i have to set the same property names (Key, InsertDate) by joins over multi columns?

Convert SQL query to Nhibernate Criteria

My SQL query:
select [CompanyId]
from dbo.Bussiness_Company
where [BussinessId] in (11,12,13)
group by [CompanyId]
having COUNT(distinct [BussinessId])=3
Explain:
I have a table Bussiness_Company table :
Bussiness_Company
Id*
BussinessId
CompanyId
My data:
Id---------BussinessId------------CompanyId
1----------10---------------------100
2----------11---------------------100
3----------12---------------------100
Resaul query
CompanyId
100
Thank for any hepl!
Sloved:
This is my code:
DetachedCriteria detachedCriteria = DetachedCriteria.For<BussinessCompany>();
detachedCriteria.SetProjection(Projections.Property("Company"));
detachedCriteria.SetProjection(Projections.GroupProperty("Company"));
Disjunction disjunction = Restrictions.Disjunction();
foreach (Bussiness bussiness in list)
{
disjunction.Add(Restrictions.Eq("Bussiness", bussiness ));
} detachedCriteria.Add(disjunction).Add(Restrictions.Eq(Projections.CountDistinct<BussinessCompany>(m => m.Bussiness), list.Count));
IList<Sonomi.Core.BusinessObjects.Bussiness> bussiness =
bussinessUnitManager.CreateCriteria().Add(Subqueries.PropertyIn("Id", detachedCriteria)).List
<Sonomi.Core.BusinessObjects.BussinessUnit>();
dgrCer.DataSource = bussiness;
dgrCer.DataBind();
You can try a such QueryOver code:
var bussinessIdCount = 3;
var bussinessIds = new[] { 11, 12, 13 };
Bussiness_Company bussinessCompany = null;
session.QueryOver(() => bussinessCompany)
.WhereRestrictionOn(() => bussinessCompany.BussinessId).IsIn(bussinessIds)
.Select(Projections.Group(Projections.Property(() => bussinessCompany.CompanyId)))
.Where(Restrictions.Gt(Projections.CountDistinct(() => bussinessCompany.BussinessId), bussinessIdCount));

LINQ Where Exists GROUP BY

How can i convert this in LINQ?
SELECT B.SENDER, B.SENDNUMBER, B.SMSTIME, B.SMSTEXT
FROM MESSAGES B
WHERE EXISTS ( SELECT A.SENDER
FROM MESSAGES A
WHERE A.SENDER = B.SENDER
GROUP BY A.SENDER
HAVING B.SMSTIME = MAX( A.SMSTIME))
GROUP BY B.SENDER, B.SENDNUMBER, B.SMSTIME, B.SMSTEXT ;
Thanks a lot :)
EDIT!!
Resolved with:
var Condition = "order by SMSTime desc";
IEnumerable<ClassMessaggio> messaggi = Database.Select<ClassMessaggio>(Condition);; // Load all but sorted
ElencoConversazioni = messaggi.GroupBy(m => new { m.Number })
.Select(g => g.OrderByDescending(m => m.SMSTime).First()).ToObservableCollection();
Try
db.Messages.Where(b => b.SmsTime == Messages.Where(a => a.Sender == b.Sender)
.Max(a => a.SmsTime))
Or
db.Messsages.GroupBy(m => new { m.Sender, m.SendNumber })
.Select(g => g.OrderByDescending(m => m.SmsTime).First())
Where db is your DataContext.
To show the list of conversations along with "the last message of every contact", you could try something like:
// a query to find the last Sms time per sender
var lastSmsQuery = from m in db.messages
group m by m.Sender into grouping
select new
{
Sender = grouping.Key,
LastSmsTime = grouping.Max(x => x.SmsTime)
};
// a query to find the messages linked to the last Sms per sender
var lastMessageQuery = from m in db.messages
join l in lastSmsQuery on new { m.Sender, m.SmsTime } equals new { l.Sender, l.LastSmsTime }
select m;
The 2-query method used is similar to that of this question from earlier today - Convert SQL Sub Query to In to Linq Lambda