I am trying to join multiple datatables to create a single datatable. Here is the query.
var row = from r0w1 in dt_vi.AsEnumerable()
join r0w2 in dt_workcenter.AsEnumerable()
on r0w1.Field<int>("wcID") equals r0w2.Field<int>("iD")
join r0w3 in dt_recipe.AsEnumerable()
on r0w1.Field<int?>("curingRecipeID") equals r0w3.Field<int?>("recipe_id") join r0w4 in dt_defect.AsEnumerable()
on r0w1.Field<int?>("defectID") equals r0w4.Field<int?>("defect_id") into ps
from r0w4 in ps.DefaultIfEmpty()
select r0w1.ItemArray.Concat(r0w2.ItemArray.Concat(r0w3.ItemArray.Concat(r0w4.ItemArray))).ToArray();
foreach (object[] values in row)
dt.Rows.Add(values);
I tried to join r0w1 & r0w4 as LEFT OUTER JOIN. But here I am getting the error
Object reference not set to an instance of an object
Error seems to be in
r0w4.ItemArray
May be r0w4 is not getting any value. What could be the possible reason ?
The problem is ps.DefaultIfEmpty() will return the default value (null in this case) when no row match and thus it is throwing that error.
You can change it like this:-
r0w3.ItemArray.Concat(r0w4 != null ? r0w4 .ItemArray : new object[] {}))
Related
I have two tables A and B,which I can outer join with linq. I need a way to find if it is possible to have a boolean along with the query if the outer join has a match. For example, I need a boolean to be true if a record is present in tableA and not in tableB. This can be done in SQL using IF, I was wondering if there was something similar in Linq
var result = from a in tableA
join b in tableB on a.Id equals b.userId into group1
from g1 in group1.DefaultIfEmpty()
select new{id = g1.Id,userId = g1.userId,boolIsPresent =(present in tableA not in tableB)}.ToList();
Currently, you're performing an inner join, not a left outer join, which means only records/objects that exist in both tables are retrieved. thus your bool boolIsPresent would always be true.
edit:
to test if a record is present in tableA and does not have a matching record in tableB just check if g1 != null, i.e:
var result = from a in tableA
join b in tableB on a.Id equals b.userId into group1
from g1 in group1.DefaultIfEmpty()
select new
{
id = g1 != null? g1.Id : enterDefault,
userId = g1 != null? g1.userId : enterDefault,
boolIsPresent = g1 != null
}.ToList();
It will be something like
boolisPresent = b != null
Once you get an Outer join working!
I am trying to left join three tables using defaultIfEmpty to assign null value if there is no match in the second table and then i am using the second table values to join the third table.
var test = (from Eqpt in Eqpts
join SystemEqpt in FleetSysEqpt on SystemEqpt.ID equals eqpt.SwCompanyEqptKey into sysEqptTemp
from a in sysEqptTemp.DefaultIfEmpty()
join System in System on a.SwFleetSystemKey equals System.ID
)
I am getting null object reference error when 'a' becomes null. Any Suggestions to check whether 'a' is null while joining.
You simply need to add a where condition
var test = (from Eqpt in Eqpts
join SystemEqpt in FleetSysEqpt on SystemEqpt.ID equals eqpt.SwCompanyEqptKey into sysEqptTemp
from a in sysEqptTemp.DefaultIfEmpty()
join System in System on a.SwFleetSystemKey equals System.ID
where a != null
)
How can I join two different tables based on a condition?
I have my query as under:
var myquery = from p in db.tbl1
join q in db.tbl2 on p.field1 equals q.field1
join r in db.tbl3 on q.field2 equals r.field2
Till here everything is fine, now I want to add 1 more join to a table but it should be based on a condition like:
if(q.field3 == 1)
join s in db.tbl4 on q.field4 equals s.field4
else if(q.field3 == 2)
join s in db.tbl5 on ....
So basically I want to join to different tables based on the value of q.field3.
You're not going to be able to conditionally join based on the value of a single row. The idea of joining is that you're joining based off of all of the rows. Conditionally determining what/how to join based on some value outside of the query would make sense.
What you can do is do both joins unconditionally, but choose which result to use conditionally for each row. Obviously this will only work if the tables are of the same type, or if you first project s1 and s2 into a common type (using let)
var myquery = from p in db.tbl1
join q in db.tbl2 on p.field1 equals q.field1
join r in db.tbl3 on q.field2 equals r.field2
join s1 in db.tbl4 on q.field4 equals s1.field4
join s2 in db.tbl5 on q.field5 equals s2.field5
let s = q.field3 == 1 ? s1 :
q.field3 == 2 ? s2 : null
This should be able to be translated by the query provider into a CASE statement.
Hi i am trying to join two tables in c#. the join code is given below. The problem is that when there is null value for tourid in tb_abc then in will not include that row from tb_abc in the list.
return (from p in context.tb_abc
from o in context.tb_Second
where o.id==p.tourId
where p.driverId == driverId
select new abcBean
{
id=p.id,
name=o.name
}).ToList<abcBean>();
Can anyone tell me what i am doing wrong
You are not doing an inner join in that query. You are doing a cross join, its where you have two tables and join each record to every other record.
If you want to include rows that return null on one of the constraints you need a left outer join.
return (from p in tb_abc
join o in tb_Second on p.tourId equals o.id into po
where p.driverId == driverId
from subpo in po.DefaultIfEmpty()
select new abcBean
{
id=p.id,
name=(subpo == null ? String.Empty : subpo.Name)
}).ToList();
Consider these two sql statements:
The first a cross join:
select id, name
from tb_abc o,
tb_Second p
where
o.id = p.tourID
and p.driverID = #driverID
The second a left outer join:
select id, name
from tb_abc o
LEFT OUTER JOIN tb_Second p on o.id = p.tourID
where
p.driverId = #driverID
The second will give you one set of the records, that include the null value of o.id.
The first will give you something of a Cartesian product which you rarely want.
Linq's DefaultIfEmpty() puts the default value (null) into the record if it doesnt find a match for the one side, so it behaves like the left outer join.
you can use left outer join like
return (from p in context.tb_abc
join o in context.tb_Second on o.id==p.tourId into gt
where p.driverId == driverId
from subsecond in gt.DefaultIfEmpty()
select new abcBean
{
id=p.id,
name=(subsecond == null ? String.Empty : subsecond.Name)
}).ToList<abcBean>();
I am trying to write left outer join using LINQ. The SQL looks like,
SELECT *
FROM Table1 td1
LEFT OUTER JOIN Table2
ON td1.ColumnName = td2.ColumnName
WHERE td2.ColumnName IS NULL
ORDER BY SomeColumns
If I run this query in SQL Query analyzer, it returns say 100 records. And my converted LINQ code returns 105 records.
I have written LINQ in 2 ways as,
Method 1:
var data= (from td1in Table1
join td2 in Table2.Where(a => a.ColumnName == (int?)null)
on td1.ColumnName equals td2.ColumnName into outer
from x in outer.DefaultIfEmpty()
orderby SomeColumns
select td1);
Method 2: This gives an exception as, failed to enumerate results
var data = from td1 in Table1
join td2 in Table2
on td1.ColumnName equals td2.ColumnName into outer
from item in outer.DefaultIfEmpty()
where item.ColumnName.Value == (int?)null
orderby somecolumns
select td1 ;
The column used in where clause is nullable int type.
The result returned in SQL analyzer seems to be correct one.
Please help me in getting the identical results.
Thanks
Try this query:
var data = from td1 in Table1
join td2 in Table2
on td1.ColumnName equals td2.ColumnName into outer
from item in outer.DefaultIfEmpty()
where item == null
orderby somecolumns
select td1 ;
In your original query that line item.ColumnName.Value == (int?)null was wrong, because you tried to retrieve value for all ColumnName even if item was null. I corrected it and now it should work fine.