c# Linq How to write Innter Join using if condition - c#

Here I have Two Tables Like
Employee
Id IsAccepected(bool) AccepectedBy EmpId
1 0 0 E1-1
2 1 2 E1-2
3 1 1 C1-1
Login
Id name
1 John
2 Mick
3 smith
Here my Question if IsAccepected==True then I need to Fetch Accepted By Record from Login Table
var x=(from n i in _db.EMployee
WHERE n.Empid='E1-1'
select n).Tolist();
foreach(var item in x){
if(item.IsAccepected==True){
.......
}
But I don't Need all those is it Possible to Write this condition Within The Linq

i guess you need this sql query need to be in linq right?
select b1.*,isnull((select 1 from A as a1 where a1.AccepectedBy=b1.Id and a1.EmpId='E1-2'),0) as isaccepted from B as b1

Something like below should work:
var x = from e in _db.Employee join l in _db.Login on e.AcceptedBy equals l.ID where e.Accepted == true select l;

Use this code by left join method-
select Login.name,Employee.EmpId from Employee left join Login on Employee.AccepectedBy=Login.Id where Employee.[IsAccepected(bool)]=1

Related

How to Select all records from table 1 and exclude matching records from table 2 using LINQ

I want to select all records from table 1 and if there any match between table 1 and table 2 then I have to exclude that records.
Note: The requirement is I have to use left outer join for that..
For example,
table 1 table 2
1 1
2 2
3
Output should be 3
I have written query in SQL but I want this in SQL LINQ like from a in dbContext.Table1....
select t1.*
from table1 t1
left outer join table2 t2 on t1.ID = t2.ID and t1.Code = t2.Code
where s.ID is null
How to solve this?
var result = (from primer in one
join primer2 in two on primer.id equals primer2.id into gj
where gj.Count()==0
select new
{
primer.id
}).ToList();
Where ONE - it is first table, TWO - it is second table.
Instead of
...select new
{
primer.id
}...
You can use
...
select primer
...

GROUP BY, ORDER BY and taking first in LINQ

Suppose I have a table with two columns:
TABLE A
-------
ProjectID NUMBER
STATUS VARCHAR2(6) // either 'CLOSED' or 'NEW'
There could be maximum two entries for a ProjectID with the two possible values of STATUS and the combination (ProjectID, STATUS) is unique.
I need to select only those ProjectID's that have status 'NEW'. Also, if for a projectID, there are two entries with different statuses (NEW and CLOSED), I don't want it in the output.
I tried using group by, then ordering the resultset descending (so as to get 'NEW' row for a project ID first) and then taking the first row in LINQ, similar to this:
var query = (from a in context.A.Where(o => o.STATUS == 'NEW')
group a by a.ProjectID into groups
select groups.OrderByDescending(o => o.ProjectID)
.ThenBy(o => o.STATUS)
.FirstOrDefault());
Butt it's resulting into an "APPLY" clouse in the query which is resulting into an error. Apparantly, Oracle 10g doesn't support it.
Any help is appreciated.
Something like this, perhaps?
SQL> with test (projectid, status) as
2 (select 1, 'new' from dual union -- should be returned
3 select 2, 'new' from dual union
4 select 2, 'closed' from dual union
5 select 3, 'closed' from dual union
6 select 4, 'new' from dual -- should be returned
7 )
8 select projectid
9 from test
10 group by projectid
11 having min(status) = max(status)
12 and min(status) = 'new';
PROJECTID
----------
1
4
SQL>
Proper tu use having count(distinct STATUS=1) :
create table tableA( ProjectID int, STATUS varchar2(10) );
insert all
into tableA values(1 ,'NEW')
into tableA values(1 ,'CHANGED')
into tableA values(2 ,'NEW')
into tableA values(3 ,'CHANGED')
select * from dual;
/
select * from
(
select ProjectID, max(STATUS) STATUS
from tableA
group by ProjectID
having count(distinct STATUS)=1
)
where STATUS = 'NEW';
I believe I have accomplished what you want, using a subquery in LINQ.
var query = (from a in context.A
where (from b in context.A
where b.ProjectID == a.ProjectID
select new { a.ProjectID, a.STATUS }).Distinct().Count() == 0
&& a.STATUS == "NEW"
select a.ProjectID).ToList();
Essentially, the outer query just makes sure that each a record has a NEW status, and the inner query makes sure that there are no two distinct records with the given ProjectID, because if there are, one is CLOSED. I avoided using a GROUP BY since you said your database does not support LINQ's way of doing it.
I hope I understood your problem correctly, and I hope this helps!

How to retrieve all columns from table1 and matching columns from table2(Left outer join) using Linq

I have to retrieve all the columns from table1 and matching columns from table2. I have a stored procedure as :
alter Procedure [dbo].[usp_Property]
#UserId bigint =null
As
Begin
select P.PID, P.PropertyName, P.SBUArea, P.ListedOn,
P.Availability, P.Price, F.UserID, F.PID as FavProjId
from dbo.Property P left outer join dbo.Favorite F
on (F.PID=P.PID And F.UserID=#UserId)
I want to get Linq query for the same. So far I tried with something like
//User Id comes from session..
//var userId
var result=(from p in Properties
join f in Favorites
on p.PID equals f.PID into r
from r1 in r.DefaultIfEmpty()
where r1.UserID==userId
select new
{
p.PID,
p.PropertyName,
p.SBUArea, p.ListedOn,
r1.UserId
});
Can anyone please correct me. I want to use left outer join or any other alternate thing here.
If I beautify your SP's code, I get this:
DECLARE #UserId int
SET #UserId = 12435
SELECT
P.PID
,P.PropertyName
,P.SBUArea
,P.ListedOn
,P.Availability
,P.Price
,F.UserID
,F.PID AS FavProjId
FROM Property AS P
LEFT JOIN Favorite AS F
ON (F.PID=P.PID AND F.UserID = #UserId)
Now I wonder if you need that UserId in the WHERE clause of the SQL, or really in the join.
But anyway, here the LINQ-equivalent of exactly that SQL:
System.Int64 __UserId = 12435;
var query = (
from P in Repo.Property
from F in Repo.Favorite
.Where(fav=> fav.PID == P.PID && fav.UserID == __UserId)
.DefaultIfEmpty() // <== makes join left join
select new
{
PID = P.PID
,PropertyName = P.PropertyName
,SBUArea = P.SBUArea
,ListenOn = P.ListedOn
,Availabiity = P.Availability
,Price = P.Price
,UserId = F.UserID
,FavProjId = F.PID
}
);
var data = (query).ToList();
Use anonymous objects in your selection
var result = from t in table1
join x in table2
on t.id equals x.id
select new { id = t.id, col1 = t.col1, col2 = x.col2 }
If you will put the where clause after join you may get null reference exception because DefaultIfEmpty returns default value for non matching rows. You can filter the records before joining itself like this:-
var result=(from p in Properties
join f in Favorites.Where(x => x.UserID == userId)
on p.PID equals f.PID into r
from r1 in r.DefaultIfEmpty()
select new
{
p.PID,
p.PropertyName,
p.SBUArea,
p.ListedOn,
r1.UserId
});
Please note you need to access properties of Favorites using r1.
Update:
As far as I have understood you need all records from Property table and only matching rows from Favorite table. But you have a filter on your Favorite table so the ultimate data source will differ. Let me make my point clear by this example:-
Suppose you have following data in Property table:-
PID PropertyName Availability Price
1 aaa true 20
2 bbb false 10
3 ccc true 50
4 ddd false 80
5 eee true 55
6 fff false 70
and Favorite table like this:-
FID PID UserId
1 4 1001
2 2 1005
3 5 1007
And let's say you want all records for UserId 1005, then the result should contain all the property Id's from 1 till 6 even if UserId 1005 doesn't match for property Id's 4 & 2 right? So the query above is as per this understanding. Check this Fiddle with same example and output.

linq multible join does not work in some empty tables

hi I'm using 4 tables..
Sometimes it does not have information in the this tables(education or address or certificate)
so the results are coming empty..
If have information how can I say?
example
**PersonTable**
PersonId PersonName
1453 george
**Certificate Table**
CertificateId PersonId CertificateName ( 0 records)
**Addres Table**
AddresId PersonId Adress
1 1453 ......
2 1453 .....
3 1453 ......
4 1453 ......
5 1453 ........
**EducationTable**
EducationId PersonId Education
1 1453 school name
**BankTable**
BankId PersonId Bank ( 0 records )
Person table = 1 records
Certificates = 0 records
Address = 5 records
Education = 1 records
Bank = 0 records
var query = (from p in DbEntities.t_Person
join q in DbEntities.t_Address on p.PersonId equals q.addressId
join n in DbEntities.t_Education on p.PersonId equals n.EduId
join j in DbEntities.t_Certificate on p.PersonId equals j.CertificateId
join f in DbEntities.t_BankAccount on p.PersonId equals f.BankId
where p.PersonId.Equals(id)
select new { p, q, n, j, f }).FirstOrDefault();
return query values null ,
I do not see why these values​​?
Person table = 1 records
Address = 5 records
Education = 1 records
I thought about it, but did not
var query = (from p in DbEntities.t_Person
where p.PersonId.equlas(id)
select p).singleOrDefault();
query = from p in dbEntities.Address
WHERE P.AddressId.equlas(query.PersonId)
select p;
It's because you're doing an INNER JOIN, which will only return records if all join conditions are met! It looks like you want to do a LEFT JOIN, which will return all rows from the left table, and from the right table it will return any record that is found, and null otherwise. Here is a good post explaining the different types of joins, with diagrams!
The Linq-to-Entities way to do a left join is DefaultIfEmpty(). See MSDN for a usage example.

The correct way to specify a sub query of a subquery using linq

results = (from r in results
where r.Buildings.Any(x=>x.StructuralElements.Any(s=>s.VALUE == Model.Bedrooms.ToString() && s.CATEGORY=="RM"))
select r);
I think I'm missing joins here. But maybe they are implied? The execution runs so long I can't do a watch to evaluate the generated query expression
The biggest problem in this query is this:
--#p1 = Models.Bedrooms.ToString()
--#p2 = "RM"
SELECT * FROM Results r WHERE EXISTS
(SELECT x.* FROM Results tr JOIN Buildings x ON tr.SomeID=x.SomeID WHERE tr.ID = r.ID AND EXISTS
(SELECT s.* FROM StructuralElements s JOIN Buildings tx ON tx.OtherID = s.OtherID WHERE tx.ID=x.ID AND s.VALUE = #p1 AND s.Category = #p2))
Do you see why this would be bad? For every Result, you're running a subquery (which in itself is running a subquery). This is going to be an exponential increase in time/processing as you start adding things at the root levels (Results and Buildings) because of these nested subqueries. Your best bet is to use joins and get distinct r values after you're done. The SQL would like like this:
SELECT DISTINCT
r.*
FROM
Results r
INNER JOIN Buildings x ON x.SomeID = r.SomeID
INNER JOIN StructuralElements s ON s.OtherID = r.OtherID
WHERE
s.VALUE = #p1 AND s.CATEGORY = #p2
The reason this will work is that when you join, if there are more than one to join back, it will duplicate the original row. The following illustration shows
IDs
R X S
1 - -
Join X
1 1 -
1 2 -
1 3 -
Join S
1 1 1
1 1 2
1 2 5
1 2 6
Assuming S=2 and S=6 meet your criteria, then it will return (in R,X,S form) rows 1,1,2 and 1,2,6. Getting just the distinct r in this case will only return R=1, which is what you're trying to accomplish. Using EF, the relationships already exist, so you don't need to do anything extra, just reference the columns you're trying to filter by:
results = (from r in results
from x in r.Buildings
from s in x.StructuralElements
where s.VALUE == Model.Bedrooms.ToString() && s.CATEGORY=="RM"
select r).Distinct();
This is the SelectMany operator at play (which takes a collection and flattens out subcollections into a single collection).

Categories