Inner select query in linq query c# - c#

I want to check values that are present in other table, not from fixed list or array. here is an example of what I need. Actually I am querying EF.
Database_EF db = new Database_EF();
var listA = (from a in db.a
where a.id in
(from b in db.b
join c in db.c on b.id equals c.id
where c.col1 equals 'something'
select b.id)
select a.id).ToList();
I am new to linq. Thanks.

Should be something like this:
var listA = (from a in db.a
where (from b in db.b
join c in db.c on b.id equals c.id
where c.col1 == "something"
select b.id).Contains(a.id)
select a.id).ToList();

Related

EF core 2.1 select/distinct

I'm using sql profiler to see sql generated by Ef core2.1,
this is my linq query :
var resulat = (from a in A
join b in B equals a.level=b.level
where ...
select new M1 {AId = a.id}).Distinct();
(from r in resulat
join c in C equals r.AId = c.AId
select new M2
{
CId = c.Id,
level = _helper(c.level)
}).Distinct();
Sql generated:
select t.AId,c.Id,c.level
from
(
select distinct a.id
from A a
inner join B b on a.level=b.level
where ...
) as t
inner join C c on t.AId = c.AId
What i want as result is :
select distinct c.Id,c.level
from
(
select distinct a.id
from A a
inner join B b on a.level=b.level
where ...
) as t
inner join C c on t.AId = c.AId
I have tried also using select/distinct with result IQueryable, but the sql generated is the same.
what i missed in my linq query or what i have to add to have this sql query
That's what worked for me:
Delete Distinct() from result query, this avoid adding t.AId to my selection.
Delete a helper method from one of my selection fields performe adding Distinct() to final query.
This is my query after correction:
var resulat = from a in A
join b in B equals a.level=b.level
where ...
select new M1 {AId = a.id};
(from r in resulat
join c in C equals r.AId = c.AId
select new M2
{
CId = c.Id
level = c.level
}).Distinct();
Many thanks for your comments, it really helped me.
I'm always a fan of querying the data you want directly from the table (well, DbSet) that returns the data. The process looks a bit like these steps:
I want C.Id and C.Level
That's context.Cs.
Which Cs do I want?
The ones that have a parent A, of which at least one B has the same 'level' as A and meets a couple of other criteria (the where ...).
That amounts to:
from c in context.Cs
where context.Bs.Any(b => b.level == c.A.level && <other criteria>)
select new { c.Id, c.Level }
If the where ... also contains filter criteria for A you can add predicates like && c.A == ... to the where.
Note that I assume a navigation property c.A to be present, otherwise to be created, because C has AId.

LINQ Left Join 3 tables with OR operator

I have this SQL query:
SELECT * FROM [CMS_MVC_PREPROD].[dbo].[T_MEMBER] m
left outer join [CMS_MVC_PREPROD].[dbo].[T_COMPANY] c
ON m.Company_Id = c.Id
left outer join [CMS_MVC_PREPROD].[dbo].[T_ADRESSE] a
ON m.Id = a.Member_Id OR a.Company_Id = c.Id
But i could not translate it to Linq
I have some trouble with this line in particular:
ON m.Id = a.Member_Id OR a.Company_Id = c.Id
EDIT: I try this query from Ehsan Sajjad
from m in db.Member
join c in db.T_Company on m.Company_Id equals c.Id into a
from c in a.DefaultIfEmpty()
from ta in db.T_Address
where m.Id == ta.Member_Id || ta.Company_Id == c.Id
But it only returns members who have an address and i want all members. Maybe it will work with a full join
Thanks in advance
LINQ only supports equi-joins directly. You'll have to use a different query pattern:
from m in db.MEMBER
//add join to "c" here
from a in (
from a db.ADRESSE
where m.Id == a.Member_Id || a.Company_Id == c.Id
select a).DefaultIfEmpty()
select new { m, a }
Just a sketch. The trick is using DefaultIfEmpty on a subquery. Both L2S and EF can translate this to an OUTER APPLY which is equivalent to a LEFT JOIN.
You can write this way to make it work:
from m in db.Member
join c in db.T_Company on m.Company_Id equals c.Id into a
from c in a.DefaultIfEmpty()
from ta in db.T_Address
where m.Id == ta.Member_Id || ta.Company_Id == c.Id

Return navigation property within join query

In building a patient appointment application I need to return patients with its navigation property patientDetails while those returned match a sessionId that is not directly deduced from the patient but rather from a series of other navigation properties. This in itself is not difficult, like plain SQL joins can be used, it's just that my navigation property patientDetails is never included.
The include path is correct, in case anyone asks.
using (DbEntities db = new DbEntities())
{
List<tblPatient> res = (from s in db.tblSessions
join b in db.tblBookings on s.id equals b.sessionId
join r in db.tblReferrals on b.referralId equals r.id
join a in db.tblAttendanceStatus on b.attendanceStatus equals a.id
join p in db.tblPatients.Include("tblPatientDetail") on r.patientId equals p.id
join pd in db.tblPatientDetails on p.patientDetailsId equals pd.id
where s.id == id
select p).ToList();
return res;
}
It appears to make no difference whether or not I include the .include.
What have I overlooked?
Includes are ignored when you use join or group by. You can change your query to use where instead
List<tblPatient> res = (from p in db.tblPatients.Include("tblPatientDetail")
where
(from s in db.tblSessions
join b in db.tblBookings on s.id equals b.sessionId
join r in db.tblReferrals on b.referralId equals r.id
join a in db.tblAttendanceStatus on b.attendanceStatus equals a.id
where r.patientId == p.id
where s.id == id
select 1).Any()
select p).ToList()

LINQ Join with multiple AND conditions

I want to join two entities in my MVC application for data Processing through the LINQ join.
For that I am trying to write the query like,
from enumeration in db.Enumerations
join cust in db.Customers on ( enumeration.Value equals cust.lkpStatus &&
enumeration.EnumerationTypeID.Contains('Cust')
But I am getting Problem with this Query, So please give me some suggestion on this.
Join should be made like this:
var joinQuery =
from t1 in Table1
join t2 in Table2
on new { t1.Column1, t1.Column2 } equals new { t2.Column1, t2.Column2 }
...
Try this solution:
from enumeration in db.Enumerations.Where(e =>
e.EnumerationTypeID.Contains('Cust'))
join cust in db.Customers on enumeration.Value equals cust.lkpStatus
select enumeration;
This one?
var data = from c in db.Enumerations
from d in db.Customers
where c.Value.Equals(d.lkpStatus)
&& c.EnumerationTypeID.Contains('Cust')
select c;
This works
var data = from c in db.Enumerations from d in db.Customers where c.Value==d.lkpStatus && c.EnumerationTypeID.Contains('Cust') select c;

How do I build up a LINQ => SQL / entities query (with joins) step-by-step?

I have the following two LINQ queries:
public int getJobsCount()
{
var numJobs =
(from j in dbConnection.jobs
join i in dbConnection.industries on j.industryId equals i.id
join c in dbConnection.cities on j.cityId equals c.id
join s in dbConnection.states on j.stateId equals s.id
join pt in dbConnection.positionTypes on j.positionTypeId equals pt.id
select j).Count();
return numJobs;
}
public List<Job> getJobs()
{
var jobs =
(
from j in dbConnection.jobs
join i in dbConnection.industries on j.industryId equals i.id
join c in dbConnection.cities on j.cityId equals c.id
join s in dbConnection.states on j.stateId equals s.id
join pt in dbConnection.positionTypes on j.positionTypeId equals pt.id
orderby j.issueDatetime descending
select new Job { x = j.field, y = c.field, etc }
).Skip(startJob - 1).Take(numJobs);
return jobs;
}
There's a lot of duplicate code in there - the "from", and "join" lines are identical, and I'll be adding in some "where" lines as well that will also be identical.
I tried adding a method that returned an IQueryable for the first part:
public IQueryable getJobsQuery()
{
var q =
from j in dbConnection.jobs
join i in dbConnection.industries on j.industryId equals i.id
join c in dbConnection.cities on j.cityId equals c.id
join s in dbConnection.states on j.stateId equals s.id
join pt in dbConnection.positionTypes on j.positionTypeId equals pt.id;
return q;
}
...but I get "a query body must end with a select clause or a group clause".
If I add a select clause on to the end off that function, I can't call count() on the result:
// getJobsQuery:
var q = from j in dbConnection.jobs
join i in dbConnection.industries on j.industryId equals i.id
join c in dbConnection.cities on j.cityId equals c.id
join s in dbConnection.states on j.stateId equals s.id
join pt in dbConnection.positionTypes on j.positionTypeId equals pt.id
select new { a = j.y, b = c.z }
// another method:
var q = getJobsQuery();
var numJobs = q.Count(); // "IQueryable doesn't contain a definition for count"
Is there a way to build up this query step-by-step to avoid duplicating a whole lot of code?
There are two ways of writing LINQ-queries, and though it doesn't really matter witch one you use it's good to know both of them cause they might learn you something about how LINQ works.
For instance, you have a set of jobs. If you were to select all jobs with an industryId of 5 (wild guess of data-types) you'd probably write something like this:
from j in dbConnection.jobs
where j.inustryId == 5
select j;
The very same query can also be written like this
dbConnections.jobs.Where(j => j.industryId == 5);
Now, I'm not here to preach saying one way is better than the other, but here you can clearly see how LINQ using the extension-methods syntax automatically selects on the iterated object (unless you do a select), whereas in the query-syntax you must do this explicitly. Also, if you were to add inn another where clause here it would look something like this:
from j in dbConnection.jobs
where j.inustryId == 5 // not using && here just to prove a point
where j.cityId == 3 // I THINK this is valid syntax, I don't really use the query-syntax in linq
select j;
While in the extension-methods you can just append more method-calls like so:
dbConnections.jobs.Where(j => j.industryId == 5)
.Where(j => j.cityId == 3);
Now this is good to know cause this means you can just put your linq-query inside a function an continue querying it. And all you need to do to make it work in your case is just explicitly select the starting variable j, or all the variables you need like so:
var q =
from j in dbConnection.jobs
join i in dbConnection.industries on j.industryId equals i.id
join c in dbConnection.cities on j.cityId equals c.id
join s in dbConnection.states on j.stateId equals s.id
join pt in dbConnection.positionTypes on j.positionTypeId equals pt.id;
select new {j = j, i = i, c = c, s = s, pt = pt };
return q;
Then you should be able to do for instance this:
getJobsQuery().Where(a => a.i.id == 5); // I used a as a name for "all", like the collection of variables
or using the query-syntax
from a in getJobsQuery()
where a.i.id == 5
select a;
Would this be better solved by returning a set of data (e.g. the common data) and querying for a subset of that data?
E.g. [pseudocode]
var allJobs =
(from j in dbConnection.jobs
join i in dbConnection.industries on j.industryId equals i.id
join c in dbConnection.cities on j.cityId equals c.id
join s in dbConnection.states on j.stateId equals s.id
join pt in dbConnection.positionTypes on j.positionTypeId equals pt.id
select j);
var myJobs = allJobs.OrderBy(j => j.issuedate).skip(expr).Take(allJobs.Count);
or similar...

Categories

Resources