Linq join tables using a flag column - c#

I need join 3 tables using a column flag called cashbillingtype_id, this determines what table will joined.
For example i have this Datatable called [CashBillings]:
cashbilling_id cashbillingtype_id
1 1
2 1
3 2
When:
cashbillingtype_id = 1 means: CashBillingsBills
cashbillingtype_id = 2 means: CashBillingsReturns
cashbillingtype_id = 3 means: CashBillingsCancellations
Now each table (Bills, Returns, Cancellations) have inside a column called cashbillingBRC_total i need to get this column data according the flag main datatable.
I Tryed:
(from CashBillings in _DataTable_Billings.AsEnumerable()
join CashBillingsTypes in _DataTable_BillingsTypes.AsEnumerable()
on CashBillings.Field<Int32>("cashbillingtype_id") equals CashBillingsTypes.Field<Int32>("cashbillingtype_id")
select new
{
cashbilling_id = CashBillings.Field<Int32>("cashbilling_id"),
cashbillingBRC_total = (CashBillingsTypes.Field<Int32>("cashbillingtype_id") == 1 ?
(from CashBillingsBills in _DataTable_BillingsBills.AsEnumerable()
where CashBillingsBills.Field<Int32>("cashbilling_id") == CashBillings.Field<Int32>("cashbilling_id")
select CashBillingsBills.Field<Double>("cashbillingbill_total")).LastOrDefault()
:
(CashBillingsTypes.Field<Int32>("cashbillingtype_id") == 2 ?
(from CashBillingsReturns in _DataTable_BillingsReturns.AsEnumerable()
where CashBillingsReturns.Field<Int32>("cashbilling_id") == CashBillings.Field<Int32>("cashbilling_id")
where CashBillingsReturns.Field<Int32>("cashbillingreturnstatus_id") == 1 // Only Processed
select CashBillingsReturns.Field<Double>("cashbillingreturn_total")).LastOrDefault()
:
(from CashBillingsCancellations in _DataTable_BillingsCancellations.AsEnumerable()
where CashBillingsCancellations.Field<Int32>("cashbilling_id") == CashBillings.Field<Int32>("cashbilling_id")
select CashBillingsCancellations.Field<Double>("cashbillingcancellation_total")).LastOrDefault())
),
}).Aggregate(DataTable_Billings, (dt, result) => { dt.Rows.Add(result.cashbilling_id,
result.cashbillingtype_id,
result.cashbillingtype_name,
result.cashbillingBRCstatus_id,
result.cashbillingBRCstatus_name,
result.cashbillingcustomer_fullname,
result.cellar_name,
result.cashbillingBRC_subtotal,
result.cashbillingBRC_discount,
result.cashbillingBRC_isv,
result.cashbillingBRC_total,
result.cashbillingBRC_date); return dt;
});
But this code is very very low efficient.

Can you check with left joining all tables initially and just operating on fields in select statement?
In case you require information on left join, see here

Related

c# Linq How to write Innter Join using if condition

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

Take any single record if matching records not available - Linq

I have linq query which has multiple records & I am filtering these records using a where clause.
Now, if the filtered records return nothing then I need to make it default to take default any single record from list.
var resultStaffGua = (from s in _db.Students
join sg in _db.StudentStaffGuardians on s.StudentID equals sg.StudentId
join g in _db.Staffs on sg.StaffId equals g.StaffID
join lr in _db.luRelationTypes on sg.RelationTypeId equals lr.RelationTypeID
join ga in _db.StaffAddresses on g.StaffID equals ga.StaffID
join ad in _db.Addresses on ga.AddressID equals ad.AddressID
where
lse.StatusID == (int?)Extension.StatusType.Active
&& lse.TenantID == tenantid
select new
{
g.FirstName,
g.LastName,
IsPrimary = sg.IsPrimaryGuardian,
se.Email,
Phone = sphon.PhoneNumber,
lr.RelationCD,
gdnr.GenderCD,
ad.Zipcode
}).Where(i=>i.IsPrimary==true);
if resultStaffGua count 0, I need one record from resultStaffGua. Thank you
if result count 0, I need one record from parentList.
Sometimes the obvious solution is the best. Why not add this after your code?
if (resultStaffGua.Count() == 0)
{
resultStaffGua = parentList.First();
}
If you want to be "clever" and do it all in one line (and I guess it would save a DB transaction too possibly) you could exchange your Where for an OrderBy and a Take.
So instead of:
).Where(i=>i.IsPrimary==true);
You could do:
).OrderBy( i => i.IsPrimary ? 0 : 1 ).Take(1);
This will prioritize any record that has an IsPrimary set to true, but it'll get one record regardless of whether any match.
Assuming that your intent is to retrieve one single record (there's at most one record with IsPrimary==true):
var query = (from s in...); //The whole query except the "where"
var resultStaffGua = query.SingleOrDefault(i=>i.IsPrimary==true) ?? query.First();
Otherwise, if the query could actually return more than one result:
var query = (from s in...);
var resultStaffGua = query.Where(i=>i.IsPrimary==true);
if(resultStaffGua.Count() == 0) resultStaffGua = new[] { query.First(); }

c# linq to entities using method based queries - trying to select where the object appears only once

i have got this table that relates the Table hardware with a table Process..
this table is called processHardware.
this table is discribed by:
IDProcessHardware
IDProcess
IDHardware
State
the field state can have 3 states (1-Insert, 2-Remove,3-Substitute)..
so i can i have this:
IDProcessoHardware IDProcesso IDHardware State
1 10 1 1
2 10 2 1
3 10 1 2
what this tell me is that the hardware with id 1 was insert on the process with the id 10
then the user insert the hardware with id 2 on the process with the id 10, and the it remove the hardware with the id 1 from the process with the id 10
by giving the id of the process i want to get the id of the hardware that were insert, this is, the id of the hardware that were remove..
so in this case the record that i will get is record number 2..because was insert, but was not removed..
after getting the ids from this table i need to relate the ids with the table hardware, this table is described by idhardware, serial number, description..
i was using linq method base..
and this was something that i did, but didnt go further after this..
var ProcessoHardware = from procHardware in db.ProcessoHardwares
where procHardware.Rem == 0 && procHardware.IDProcesso == IDProcesso
group procHardware by procHardware.IDHardware into g
select new { IDHardware = g.Key, count = g.Count() };
the query above didnt work for me...
so i want to get the records that appears only once on the table, and then relate the ids that were obtained from this query and get the info about those ids like, serial number, description(these fields are on a table called Hardware).
thanks in advance..
in sql i manage to do the query ..
SELECT *
FROM
(SELECT IDHardware ,COUNT(IDHardware) nu
FROM dbo.ProcessoHardware
WHERE IDProcesso=47
Group By IDHardware) T WHERE nu=1
how do i pass this to linq?
Firstly your SQL statement would be clearer if you used the having clause so it becomes
SELECT IDHardware, COUNT(IDHardware) nu
FROM dbo.ProcessoHardware
WHERE IDProcesso=47
GROUP BY IDHardware
HAVING COUNT(IDHardware) = 1
secondly, your SQL statement doesn't mention a field called Rem, but your LINQ states where procHardware.Rem == 0. I'm going to assume that you need to keep that filter. If so then all you need to do is add a where clause to count your group, g. Try the following
var ProcessoHardware = from procHardware in db.ProcessoHardwares
where procHardware.Rem == 0 && procHardware.IDProcesso == IDProcesso
group procHardware by procHardware.IDHardware into g
where g.Count() == 1
select new { IDHardware = g.Key, count = g.Count() };
although the literal transformation of your statement (without the Rem and hard coded ID of 47) to LINQ would be
var ProcessoHardware = from procHardware in db.ProcessoHardwares
where procHardware.IDProcesso == 47
group procHardware by procHardware.IDHardware into g
where g.Count() == 1
select new { IDHardware = g.Key, count = g.Count() };

How to return value from 2 tables in one linq query

please consider this table:
PK_Id Number Year Month Value
-------------------------------------------------------------------------
1 1 2000 5 100000
410 4 2000 6 10000
8888 1 2001 5 100
I Id=8888 and now I want to first select record with Id=8888 and second select previos year of that record*(I mean Id=1)*. How I can do this with linq and one query.
basically we have some queries that first it should find a value from a table (that may be not PK) and find Corresponding records in another tables. How I can do this with linq and one reference to database.
thanks
from a in Record
where a.PK_Id == 8888
from b in Record
where b.Number == a.Number && b.Year == a.Year - 1
select new { Current = a, Previous = b }
or
Record
.Where(a => a.PK_Id == 888)
.SelectMany(a =>
Record
.Where(b => b.Number == a.Number && b.Year == a.Year - 1)
.Select(b => new { Current = a, Previous = b })
If I understand your question right, then you need to filter the data of one table and join two tables.
You can join the tables and filter your data
var query = from c in Table1
join o in Table2 on c.Col1 equals o.Col2
where o.Col3 == "x"
select c;
or you can filter your data from one table and then join the tables (result will be the same)
var query = from c in Table1.Where(item => item.Col3 == "x")
join o in Table2 on c.Col1 equals o.Col2
select c;

Populating an ObservableCollection of ObservableCollection, delimited by two database columns

My database is as follows :
ID Date Number NumberIWishToRecord
What I wish to do is use a Linq-to-SQL query to populate an ObservableCollection<ObservableCollection<CustomClass>>.
What I want is select only the rows were Number == a given parameter.
ID refers to a person, what I want to do is get all the information about a person and store it in an ObservableCollection, so I will have an ObservableCollection<CustomClass>, with each CustomClass holding information about only one row, and each ObservableCollection<CustomClass> holding information about only one person (recorded on different days).
I then wish to select an ObservableCollection of the ObservableCollection<CustomClass> which will hold information on all people!
So, some sample data :
ID Date Number NumberIWishToRecord
1 27-06-2012 0.1933 25
1 28-06-2012 0.1933 27
1 29-06-2012 0.1933 29
2 14-06-2012 0.1933 412
2 15-06-2012 0.1741 321
So when I run my method, I want to return only the Numbers of the given parameter, in my case I will choose 0.1933.
I then want both rows where ID = 1 to be saved in an ObservableCollection<CustomClass>, and the single row where ID == 2 to be saved in another ObservableCollection<CustomClass>. Then, both of these ObservableCollections will be held in their own ObservableCollection! To illustrate :
ObservableCollection<ObservableCollection<CustomClass>>
ObservableCollection<CustomClass>
1 27-06-2012 0.1933 25
1 28-06-2012 0.1933 27
1 29-06-2012 0.1933 29
ObservableCollection<CustomClass>
2 14-06-2012 0.1933 412
How would I write a query in linq to sql that would do this ?
I'll just write a standard query syntax Linq expression to achieve this, you adapt it for your tables.
var rowsById = new ObservableCollection<ObservableCollection<row>>(
from r in _rows
where r.number == 1.2
group r by r.ID into rowIdGroup
select new ObservableCollection<row>(rowIdGroup));
If you need to convert data from the row into the CustomClass:
var rowsById = new ObservableCollection<ObservableCollection<CustomClass>>(
from r in _rows
where r.number == 1.2
group r by r.ID into rowIdGroup
select new ObservableCollection<CustomClass>(
rowIdGroup.Select(r => new CustomClass
{
ID = r.ID,
Number = r.number // add more
})));
Or if you prefer query syntax in all the expression:
var rowsById = new ObservableCollection<ObservableCollection<CustomClass>>(
from r in _rows
where r.number == 1.2
group r by r.ID into rowIdGroup
select new ObservableCollection<CustomClass>(
from gr in rowIdGroup select new CustomClass
{
ID = gr.ID,
Number = gr.number
}));

Categories