This question already has answers here:
How can you handle an IN sub-query with LINQ to SQL?
(9 answers)
Closed 6 years ago.
I'm completely new to LINQ, i want to rewrite some of mine SQL querys into LINQ (just to learn) and i'v already stuck at the beginning.
Here is SQL query :
declare #typMon varchar(200)
set #typMon = 'moneta'
select *
from [db1].[dbo].[Picking]
where number = 1000
and Group IN (Select grupa
from [db2].[dbo].[groups]
where typ = #typMon)
Subquery returns 3 output rows : http://i.stack.imgur.com/CDOwr.png
And here is what i'v write in LINQ
This part works ok :
var query = from x in db.grupyTowarowes
where x.typ == typMoneta
select new
{
x.grupa
};
Problem is here:
var test = from z in dbContext.PICKINGs
where z.Number == 1000
&& z.group IN output from 1st query
select new
{
z.id
};
var test = from z in dbContext.TBL_CSV_PICKINGs
join g in db.grupyTowarowes on Z.group equals g.grupa
where z.Number == 1000 &&
g.typ == typMoneta
select new { z.id };
Or in the Method syntax
dbContext.TBL_CSV_PICKINGs
.Where(z => z.Number == 1000)
.Join(db.grupyTowarowes.Where(g => g.typ == typMoneta)
z => z.group,
g => g.grupa,
(z,g) => z.id);
Related
I have a SQL query which I want to convert to Linq.
This is my SQL query:
SELECT
Calisanlar.CalisanId,
CovidYakalanmaTarih,
CovidBitisTarih
FROM
Calisanlar
INNER JOIN
Covids ON Calisanlar.CalisanId = Covids.CalisanId
WHERE
Calisanlar.CalisanId IN (SELECT TOP 10 CalisanId
FROM Hastaliklar
GROUP BY CalisanId
ORDER BY COUNT(*) DESC)
AND DATEDIFF(DAY, CovidYakalanmaTarih, GETDATE()) BETWEEN 0 AND 30
I wrote this C# code, but it doesn't work as expected because i didn't write "DATEDIFF(DAY, CovidYakalanmaTarih, GETDATE()) BETWEEN 0 AND 30" linq version:
var query = context.Hastaliklar
.GroupBy(x => x.CalisanId)
.OrderByDescending(grp => grp.Count())
.Select(grp => grp.Key)
.Take(10)
.ToList();
var result = from hastalik in context.Hastaliklar
join covid in context.Covids
on hastalik.CalisanId equals covid.CalisanId
where query.Contains(hastalik.CalisanId)
&& EF.Functions.DateDiffDay(covid.CovidYakalanmaTarih, covid.CovidBitisTarih)
select new SonBirAyCovidDto
{
CalisanId = covid.CalisanId,
CovidYakalanmaTarih = covid.CovidYakalanmaTarih,
CovidBitisTarih = covid.CovidBitisTarih
};
There is not direct translation to BETWEEN in EF Core, but you can make other condition. Also it is better to remove ToList() from first query, in this case you will have only one roundtrip to database.
var query = context.Hastaliklar
.GroupBy(x => x.CalisanId)
.OrderByDescending(grp => grp.Count())
.Select(grp => grp.Key)
.Take(10);
var result =
from hastalik in context.Hastaliklar
join covid in context.Covids
on hastalik.CalisanId equals covid.CalisanId
where query.Contains(hastalik.CalisanId)
&& covid.CovidYakalanmaTarih <= covid.CovidBitisTarih
&& EF.Functions.DateDiffDay(covid.CovidYakalanmaTarih, covid.CovidBitisTarih) <= 30
select new SonBirAyCovidDto
{
CalisanId = covid.CalisanId,
CovidYakalanmaTarih = covid.CovidYakalanmaTarih,
CovidBitisTarih = covid.CovidBitisTarih
};
I have been working with Oracle SQL for a while and am currently developing an MVC application in my spare time. At the moment I stuck on an INNER JOIN lambda expression, I have no idea how to convert the SQL statement to C# lambda expression, I've had a look at other answers similar to this question but none provide the answer and a detailed description of how to convert the statement.
Code:
SELECT
t.name, t.description
FROM
TOPICS t
INNER JOIN
TOPIC_SUBSCRIPTIONS
ON
t.TOPICID = TOPIC_SUBSCRIPTIONS.TOPICID
WHERE
TOPIC_SUBSCRIPTIONS.MEMBERID = 96;
Solution 1:
var q = db.Topics
.SelectMany(t => t.TopicSubscriptions, (t, ts) => new { t, ts })
.Where(sub => sub.ts.MemberId == 96)
.Select(sub => new { sub.t.Name, sub.t.Description });
or using LINQ style
var q = from t in db.Topics
from ts in topic.Subscriptions
where ts.MemberId == 96
select new { t.Name, t.Description };
Solution 2
var q = from t in db.Topics
join ts in db.TopicSubscriptions on t.TopicId equals ts.TopicId
into ij
from tsub in ij
where tsub.MemberId == 96
select new { t.Name, t.Description};
I am a newbie intern way over my head, I promise I have researched this thoroughly and tried many different things. The following linq query works, but I want to group rows by last and first name and then only show the rows that appear more than once. When I un-comment out the group by statement, all my aliases below become unrecognized and changing them to the actual db.table names doesn't help.
var query = from emps in db.Employees
join c in db.Cards on emps.SbiID equals c.SbiID
where c.StateID == 0 && c.CardNumberNumeric > 100000
//group emps by new {emps.Surname, emps.Name};
//orderby grp.Count() // something like 'where grp.Count > 1
select new
{
Surname = emps.Surname,
Name = emps.Name,
CorpID = emps.Identifier,
CardNum = c.CardNumber,
CostCenter = emps.EmployeeUserField.UF13,
Supervisor = (from e in db.Employees
where
e.Identifier.Equals(emps.EmployeeUserField.UF5)
select e.Surname).FirstOrDefault()
+ ", "
+ (from e in db.Employees
where e.Identifier.Equals(emps.EmployeeUserField.UF5)
select e.Name).FirstOrDefault(),
SupervisorID = emps.EmployeeUserField.UF5,
EmpCommence = emps.CommencementDateTime,
CardCommence = c.CommencementDateTime,
WorkPhone = emps.Telephone,
State = (from cf in db.ComboFields
from sp in db.StringProperties
where cf.ComboIndex.Equals(c.StateID)
&& cf.StringID.Equals(sp.StringID)
&& cf.TableName.Equals("Card")
&& cf.FieldName.Equals("StateID")
select sp.DefaultValue).FirstOrDefault()
};
this.tagsGridView.DataSource = query;
this.tagsGridView.DataBind();
I think the problem you're running into is that you're not flattening out your groups appropriately. For example:
var duplicateEmployees = db.Employees
.GroupBy(emp => emp, new EmployeeComparer())
.Where(grp => grp.Count() > 1)
.SelectMany(grp => grp.AsEnumerable());
var duplicateEmployeeInfo =
from emps in duplicateEmployees
join c in db.Cards on emps.SbiID equals c.SbiID
where c.StateID == 0 && c.CardNumberNumeric > 100000
select new
{
... what to select
};
With:
public class EmployeeComparer : IEqualityComparer<Employee>
{
public bool Equals(Employee x, Employee y)
{
return x.Surname == y.Surname && x.Name == y.Name;
}
public int GetHashCode(Employee obj)
{
unchecked { return (17 * obj.Surname.GetHashCode()) ^ (23 * obj.Name.GetHashCode()); }
}
}
This groups the employees by name, finds the groups that have a count > 1, then returns the elements of those groups. No guarantees on performance, but this should solve your issue.
I am using Linqpad and have odata connection setup.
I have a query as follows
QUERY1
void Main()
{var a = from cpuid in Computers
where cpuid.DnsHostName == "xyz"
select new {
ID = cpuid.TechnicalProductsHosted.Select (x => new { Id = x.Id }),
System_Dept = cpuid.SystemDepartment,
};
Console.WriteLine(a);
}
The output : it returns 4 ids but one department which is common among all four id's. When i query otherway round i.e
QUERY2
var a = from id in TechnicalProducts
where id.Id == "ID-15784"
select new
{System_Dept = id.Computers.Select(x => x.SystemDepartment),
Support_Team = id.Computers.Select(x => x.SupportTeam)
};
Console.WriteLine(a);
The output : 4 departments for the id. I wish to have the whole list of departments in the first case. How is it possible? In query 1 Can i take id as input for System Department and query it somehow?
the output samples
here's my sql query below:
Can you guys help me to convert this to a much cleaner one??
SELECT [PurchaseRequestID], [ProjectID],[FullName]
FROM PurchaseRequest
WHERE [PurchaseRequestID] IN
(SELECT [PurchaseRequestID] FROM PurchaseRequestDetail )
AND [PurchaseRequestID] NOT IN
(SELECT [PurchaseRequestID] FROM [PurchaseOrder] )
Though i have already converted this successfuly, i think this is not readable and needs to be rewritten:
var query = from a in db.PurchaseRequests
where
(from b in db.PurchaseRequestDetails
select new
{
b.PurchaseRequestID
}).Contains(new { a.PurchaseRequestID }) &&
!(from c in db.PurchaseOrders
select new
{
c.PurchaseRequestID
}).Contains(new { a.PurchaseRequestID })
select a;
thanks
you really don't need all those anonymous objects. Use the let keyword to introduce temporary variables instead of doing operations on the subqueries directly.
from a in db.PurchaseRequests
let b = from b in db.PurchaseRequestDetails select b.PurchaseRequestID
let c = from c in db.PurchaseOrders select c.PurchaseRequestID
where b.Contains(a.PurchaseRequestID) && !c.contains(a.PurchaseRequestID)
select a;
var query = from a in db.PurchaseRequests
where
db.PurchaseRequestDetails.Any(x => x.PurchaseRequestID == a.PurchaseRequestID) &&
!db.PurchaseOrders.Any(x => x.PurchaseRequestID == a.PurchaseRequestID)
select a;
If you have navigation properties set up, you can write the query like this:
IQueryable<PurchaseRequest> query =
from purchaseRequest in myDataContext.PurchaseRequests
where purchaseRequest.PurchaseRequestDetail.Any()
where !purchaseRequest.PurchaseOrder.Any()
select purchaseRequest;
Or this lambda/method style if you prefer...
IQueryable<PurchaseRequest> query2 = myDataContext.PurchaseRequests
.Where(purchaseRequest => purchaseRequest.PurchaseRequestDetail.Any())
.Where(purchaseRequest => !purchaseRequest.PurchaseOrder.Any());