Trouble converting a SQL Query to the equivalent LinqToEntities code? - entity-framework

The short:
A simpler way of summing up this question would be, can you apply a conditon on a join in linq?
I have the following sql query:
select cdm.cashID, cdm.DateTimeTillOpened, cdm.DateTimeTillClosed, o.OrderID, o.OrderDate
from CashDrawsMonies cdm
join Orders o on o.OrderDate >= cdm.DateTimeTillOpened
AND o.OrderDate <= cdm.DateTimeTillClosed
join Users u on o.UserID = u.UserID
where u.UserID = 'C3763CC6-D1C5-4EF3-9B83-F7AB3BF8827A'
group by cdm.cashID, cdm.DateTimeTillOpened, cdm.DateTimeTillClosed, o.OrderID, o.OrderDate
order by o.OrderDate desc
Alternative SQL#
select *
from CashDrawsMonies cdm
where exists
(
select *
from Orders o
join Users u on o.UserID = u.UserID
where
o.OrderDate >= cdm.DateTimeTillOpened and
o.OrderDate <= cdm.DateTimeTillClosed and
u.UserID = 'C3763CC6-D1C5-4EF3-9B83-F7AB3BF8827A'
)
I can convert most queries but on the join in Linq it always asks for an equal keyword and not something like >= or <= which allows me in sql to put a condition on the join. This is what makes me scratch my head as to how do I convert it then?
My linq-To-Entites model in code (c#) is set-up as:
Cache.Model.Orders
Cache.Model.CashDrawMonies
Cache.Model.Users
Appreciate the help.
Attempt 1:
var results = from o in Cache.Model.Orders
from c in Cache.Model.CashDrawMoneys
join u in Cache.Model.Users on o.UserID equals u.UserID
where c.DateTimeTillOpened >= o.OrderDate
&& c.DateTimeTillClosed <= o.OrderDate
select c;
Attempt 2:
var results = from c in Cache.Model.CashDrawMoneys
from o in Cache.Model.Orders
where c.DateTimeTillOpened >= o.OrderDate
&& c.DateTimeTillClosed <= o.OrderDate
group c by new { c.cashID, c.DateTimeTillOpened, c.DateTimeTillClosed, o.OrderID, o.OrderDate, o.UserID } into temp
from t in temp
join u in Cache.Model.Users on t.UserID equals u.UserID
where t.UserID == selectedUser.UserID
select t;
Returns no results .... : S
UPDATE:
I re wrote my sql, the second peiece of sql does exactly what I want know. Just need someone to convert it for me somehow???
SQL Version 2 Converted Using Linqer:
from cdm in db.CashDrawMoneys
where
(from o in db.Orders
join u in db.Users on o.UserID equals u.UserID
where
o.OrderDate >= cdm.DateTimeTillOpened &&
o.OrderDate <= cdm.DateTimeTillClosed &&
u.UserID == new Guid("C3763CC6-D1C5-4EF3-9B83-F7AB3BF8827A")
select new {
o,
u
}).FirstOrDefault() != null
select new {
cdm.UserID,
cdm.DateTimeTillClosed,
cdm.DateTimeTillOpened,
cdm.LooseChange,
cdm.Fivers,
cdm.Tens,
cdm.Twenties,
cdm.Fifties,
cdm.IsOpen,
cdm.IsClosed,
cdm.ClosingValue,
cdm.OpeningValue,
cdm.cashID
}
Compiles nbut produces the following error:
"The argument to DbIsNullExpression must refer to a primitive or reference type."

The joins on the first Attempt look about right. But did you turn around the comparison operator?
where c.DateTimeTillOpened **>=** o.OrderDate
&& c.DateTimeTillClosed **<=** o.OrderDate
Update:
You can't create a new object within LINQ2EF as it doesn't know how to translate that to sql.
u.UserID == new Guid("C3763CC6-D1C5-4EF3-9B83-F7AB3BF8827A")
You'll have to define the GUID before the linq statement and then use the variable
var gid = new Guid("C3763CC6-D1C5-4EF3-9B83-F7AB3BF8827A")
from cdm in db.CashDrawMoneys
where
(from o in db.Orders
join u in db.Users on o.UserID equals u.UserID
where
o.OrderDate >= cdm.DateTimeTillOpened &&
o.OrderDate <= cdm.DateTimeTillClosed &&
u.UserID == gid

Below is what I managed to get:
var results = from cdm in Cache.Model.CashDrawMoneys
where (from o in Cache.Model.Orders
join u in Cache.Model.Users on o.UserID equals u.UserID
where o.OrderDate >= cdm.DateTimeTillOpened && o.OrderDate <= cdm.DateTimeTillClosed &&
u.UserID == selectedUser.UserID
select o).FirstOrDefault() != null
select cdm;
It's pretty close to what you got and did not have to worry about the guid as it was already created for me as I had a 'selectedUser' object.
The last line could be:
select o).Any()
select cdm;
But I'm not fussed, I get the two variations but Im gonna stick with my first version.

Related

Filter entities with a field from another entity in linq query c#

I wanna join some tables in linq query. The problem is that I can not filter one of entities with field of another entity. In the below code b.createDate is not defiend, how can I do this query in linq?
From a in context.A
Join b in context.B
On a.Id equals b.AId
Join c in context.C.where(x =>
x.createDate >= b.createDate)
On b.Id equals c.BId into g
From result in
g.DefaultIfEmpty()
Select result
You have to use from instead of join in this case. As documented: Collection selector references outer in a non-where case
var query =
from a in context.A
join b in context.B on a.Id equals b.AId
from c in context.C
.Where(x => x.BId == b.Id && x.createDate >= b.createDate)
.DefaultIfEmpty()
select c;

How do you use group by and having clause in EF with parent/child relationship?

How can I write a linq to entities query that includes a group by and a having clause?
For example in SQL:
SELECT * FROM dbo.tblParent p
INNER JOIN
(
SELECT a.ID
FROM dbo.tblParent a
join dbo.tblChild c ON a.ID = c.FkParentID
WHERE a.ColValue = 167
GROUP BY A.ID
HAVING COUNT(c.ID) = 1
) t ON p.ID = t.ID
I found my own answer.
// this is far from pretty but it works as far as I can tell
Apps = (from x in context.tblParents
join t in (
from p in context.tblParents
join c in context.tblChilds
on p.ID equals c.FkParentID
where p.ColValue == 167
group c.ID by p.ID into grouped
where grouped.Count() == 1
select new { grouped.Key }) on x.ID equals t.Key
select x);

How to add a where clause to an EF query which has a grouping

I'm trying to find the number of bookings each user has made. This code works great - it does a join onto bookings and groups them and then does a count.
var bookingsByUser = from u in _repo.Users()
join b in _repo.Bookings() on u.UserId equals b.CreatedByUserId
into g
select new { UserId = u.UserId, TotalBookings = g.Count() };
However, I now want to exclude a certain restaurant, so I try to add a where clause:
var bookingsByUser = from u in _repo.Users()
join b in _repo.Bookings() on u.UserId equals b.CreatedByUserId
where b.RestaurantId != 21
into g
select new { UserId = u.UserId, TotalBookings = g.Count() };
However now I get an error "A query body must end with a select clause or a group clause". I can't seem to use "where" on the join table to filter the records before grouping. Is there a better way to do this?
Try this:
var bookingsByUser = from u in _repo.Users()
join b in _repo.Bookings() on u.UserId equals b.CreatedByUserId
where b.RestaurantId != 21
group b by u.UserId into sub
select new {
UserId = sub.Key,
TotalBookings = sub.Count()
};

LINQ to Entities: Convert SQL Sub Select

I got this figured out.
No need to answer.
The system says I have to wait 8 hours before answering my own questions. But for now the answer is below:
Here is the answer:
var startDate = DateTime.Today.AddDays(-30);
var results = (from h in Histories
join q in Quotes
on h.QuoteID equals q.QuoteID
join a in Agencies
on q.AgencyID equals a.AgencyID
where q.Status == "Inforce" &&
q.LOB == "Vacant" &&
q.EffectiveDate > startDate &&
h.Deleted == null &&
h.DeprecatedBy == null &&
h.TransactionStatus == "Committed" &&
a.DC_PLT_Roles.Any(r => r.Name == "Wholesaler")
group new {h} by new {h.PolicyNumber} into g
select new {
MaxHistoryID = g.Max (x => x.h.HistoryID),
comment = (from h2 in Histories
where h2.HistoryID == g.Max (x => x.h.HistoryID)
select h2.Comment).FirstOrDefault()
}).ToList();
The key code was:
comment = (from h2 in Histories
where h2.HistoryID == g.Max (x => x.h.HistoryID)
select h2.Comment).FirstOrDefault()
We are in the process of converting SQL / Stored Procedures to LINQ to Entities statements. And I can’t figure out the proper syntax for a sub select.
Currently I am converting this SQL:
declare #startDate DateTime
set #startDate = DATEADD(DD, -30, GETDATE())
select * from history where historyid in(
select MAX(h.historyid) as HistoryId
from History h (nolock)
inner join Quote q (nolock) on h.QuoteID = q.QuoteID
inner join Agency (nolock) a on q.AgencyID = a.AgencyID
inner join DC_PLT_EntityRoles er (nolock) on a.AgencyID = er.EntityID
inner join DC_PLT_Roles (nolock) r on er.RoleID = r.RoleID
where
q.Status = 'Inforce'
and q.LOB = 'Vacant'
and q.EffectiveDate > #startDate
and h.Deleted is null --
and h.DeprecatedBy is null --
and h.TransactionStatus = 'Committed'
and r.Name = 'Wholesaler'
group by h.PolicyNumber)
As you can see the code above is made up of two select statements. The main select (select * from history).. And a filter select (select MAX(h.historyid)…)
I got the filter select working (See below):
var startDate = DateTime.Today.AddDays(-30);
var results = (from h in Histories
join q in Quotes
on h.QuoteID equals q.QuoteID
join a in Agencies
on q.AgencyID equals a.AgencyID
where q.Status == "Inforce" &&
q.LOB == "Vacant" &&
q.EffectiveDate > startDate &&
h.Deleted == null &&
h.DeprecatedBy == null &&
h.TransactionStatus == "Committed" &&
a.DC_PLT_Roles.Any(r => r.Name == "Wholesaler")
group new {h} by new {h.PolicyNumber} into g
select new {
MaxHistoryID = g.Max (x => x.h.HistoryID)
}).ToList();
However I can’t figure out the proper syntax to set up the main select. (Basically getting the records from the History table using the HistoryID from the filter select.)
Any help would be appreciated.
Thanks for your help.
I figured it out, here is the code:
var startDate = DateTime.Today.AddDays(-30);
var results = (from h in Histories
.Include("Quote")
.Include("Quote.Agency")
where h.Quote.Status == "Inforce" &&
h.Quote.LOB == "Vacant" &&
h.Quote.EffectiveDate > startDate &&
h.Deleted == null &&
h.DeprecatedBy == null &&
h.TransactionStatus == "Committed" &&
h.Quote.Agency.DC_PLT_Roles.Any(r => r.Name == "Wholesaler")
group new {h} by new {h.PolicyNumber} into g
select new {
XMLData = (from h2 in Histories
where h2.HistoryID == g.Max (x => x.h.HistoryID)
select h2.XMLData).FirstOrDefault()
}).ToList();
The key logic is:
select new {
XMLData = (from h2 in Histories
where h2.HistoryID == g.Max (x => x.h.HistoryID)
select h2.XMLData).FirstOrDefault()
}).ToList();
Gotta love the Nested Query

NHibernate query help needed

Is it possible to convert the following query into ICriteria or LINQ, and if so, how?
SELECT Test.personid
FROM
(
SELECT r.PersonId AS personid, e.ActivityId
FROM Event e
INNER JOIN Registration r ON e.Id = r.EventId
WHERE e.ActivityId IN (1, 2)
GROUP BY r.PersonId, e.ActivityId
) AS Test
GROUP BY Test.personid
HAVING COUNT(Test.ActivityId) >= 2
var result = from r in session.Query<Registration>()
where r.Event.ActivityId == 1 || r.Event.ActivityId == 2
group r by r.Person into g
where g.Min(x => x.Event.ActivityId) != g.Max(x => x.Event.ActivityId)
select g.Key
the following states, take all Persons wich have different activityIds in there groups which is equivalent to
ActivityId == 1 || ActivityId == 2
Having Count(r.Event.ActivityId) >= 2