How to create Linq Query between a dataTable and a Sql Table - c#

I have a DataTable and a SQLTable . I want to write a linq Qurty to create a result that has Information from both tables. I wrote this code. but it runs very slowly. How can I optimize it?
var Result = (from DataRow row in dTable.Rows
from obj in db.SQLTable
where (
obj.Status != "Suspend" &&
(
(obj.Type.ToLower() == "a" && obj.Code ==
row[2].ToString()) ||
(obj.Type.ToLower() == "b" &&
obj.Code.Substring(6) == row[2].ToString())
)
select new
{
ID = obj.ID,
RowNum = row[0],
}).ToList();

I'm not sure if this is 100% the correct syntax.
The idea here is that we select calculated columns to join against. That way we're calculating the obj.Type.ToLower() and obj.Code.Substring(6) once per row (n times), rather than once per join instance (n*m times).
var Result = (from DataRow row in dTable.Rows
from obj in (db.SQLTable).Select(x => new {x.Status, ObjTypeLower = x.Type.ToLower(), x.Code, ObjCodeSub = x.Code.Substring(6)})
where (
obj.Status != "Suspend" &&
(
(obj.ObjTypeLower == "a" && obj.Code ==
row[2].ToString()) ||
(obj.ObjTypeLower == "b" &&
obj.ObjCodeSub == row[2].ToString())
)
select new
{
ID = obj.ID,
RowNum = row[0],
}).ToList();

try something like this
var result=(from e in db.Users
select e.UserID).Except(from m in db.Fi
select m.UserID).ToList();

Related

Check if parameter value is null or not inside query

In my query I am getting records based on RoleId and LocationId, some times the user may not pass location in that case I want to remove that filter and get information from all locations.
Currently I am doing this way
if(loc > 0)
{
var myResult = (from x in CSDB.Allocations
join s in CSDB.Managers
on x.ManagerId equals s.Id
Where x.RoleId == 2 && s.LocationId == loc
select new
{
x.name,
x.Date
}).ToList();
}
else
{
var myResult = (from x in CSDB.Allocations
join s in CSDB.Managers
on x.ManagerId equals s.Id
Where x.RoleId == 2
select new
{
x.name,
x.Date
}).ToList();
}
I am seeing if I can check if loc is null or not inside the query instead of using if else.
You can do something like this:
Where x.RoleId == 2 && (loc == null || s.LocationId == loc)
Also, you can do smth like this.
Where x.RoleId == 2 && (loc?.Equals(s.LocationId) ?? true)
If loc just int I would prefer to use a little bit changed #Salah Akbari answer:
Where x.RoleId == 2 && (loc == 0 || s.LocationId == loc)
Simply extract your managers and filter them if needed. That way you can as well easily apply more filters and code readability isn't hurt.
var managers = CSDB.Managers.AsQueryable();
if(loc > 0)
managers = managers.Where(man => man.LocationId == loc);
var myResult = from allocation in CSDB.Allocations
join manager in managers on allocation.ManagerId equals manager.Id
where allocation.RoleId == 2
select new
{
allocation.name,
allocation.Date
};

Shortening loop to one QUERY in LINQ

Below is a piece of code that I do in a loop:
At the beginning, in the first query, I get a list of location IDs. The list can be long.
Ultimately, I need to find for which LocationId FamiliId > 0
I have it done in a loop but I would like to do it in one question. Is it possible and if so how?
var locationIds = context.TblUsersDistricts
.Where(d => d.UserId == userId && d.ValidityTo == null)
.Select(x => x.LocationId).ToList();
int familyId = 0;
foreach(var item in locationIds) {
familyId = (from I in context.TblInsuree
join F in imisContext.TblFamilies on I.FamilyId equals F.FamilyId
join V in imisContext.TblVillages on F.LocationId equals V.VillageId
join W in imisContext.TblWards on V.WardId equals W.WardId
join D in imisContext.TblDistricts on W.DistrictId equals D.DistrictId
where(I.Chfid == chfid &&
D.DistrictId == item &&
F.ValidityTo == null &&
I.ValidityTo == null &&
V.ValidityTo == null &&
W.ValidityTo == null &&
D.ValidityTo == null)
select F.FamilyId)
.FirstOrDefault();
if (familyId > 0) break;
};
It sounds like you want:
var familyId = (
from item in locationIds
from I in context.TblInsuree
// ... etc
&& D.ValidityTo == null)
select F.FamilyId)
.FirstOrDefault();
?

assistance required to convert SQL into LINQ

i am trying to convert the following SQL into LINQ and need some assistance with the nested select clauses for the paid_amount and paid_vat and also for the select within the where clause. Ignore the index things.
here is the SQL
SELECT
tramps.gl_transaction.debtor_uri,
tramps.debtor.account_no,
tramps.gl_transaction.uri as transaction_uri,
tramps.gl_transaction.base_currency_amount,
tramps.gl_transaction.base_currency_vat_amount,
(select IsNull(sum(gltr.base_currency_amount), 0.00)
from tramps.gl_transaction gltr
where gltr.sibling_uri = tramps.gl_transaction.uri) * (-1) as Paid_Amount ,
(select IsNull(sum(gltr.base_currency_vat_amount), 0.00)
from tramps.gl_transaction gltr
where gltr.sibling_uri = tramps.gl_transaction.uri) * (-1) as Paid_Vat ,
tramps.account.property_ref,
tramps.account.sub_ledger_code,
tramps.gl_transaction.transaction_type_code,
tramps.gl_transaction.transaction_description,
tramps.gl_transaction.effective_date
FROM tramps.account, tramps.chart WITH (INDEX (PK_CHART)), tramps.gl_transaction WITH (INDEX (glt_debtor_gen)) ,tramps.debtor, tramps.receivables_register , tramps.bank_account
WHERE tramps.chart.code = tramps.account.chart_code
AND tramps.gl_transaction.debtor_uri = tramps.debtor.uri
AND tramps.gl_transaction.account_uri = tramps.account.uri
AND tramps.receivables_register.uri = tramps.gl_transaction.receivables_register_uri
AND tramps.receivables_register.bank_account_uri = tramps.bank_account.uri
AND tramps.chart.control_account = 'Debtor'
AND tramps.gl_transaction.status = 'L'
AND tramps.gl_transaction.process_status = 'Released'
AND ( (tramps.gl_transaction.generated = 'C' AND tramps.gl_transaction.sibling_uri IS NULL AND tramps.gl_transaction.written_off <> 'Y')
OR (tramps.gl_transaction.generated = 'N' AND tramps.gl_transaction.sibling_uri IS NULL) )
AND (tramps.gl_transaction.base_currency_amount +
(select IsNull(sum(gltr.base_currency_amount), 0.00)
from tramps.gl_transaction gltr
where gltr.sibling_uri = tramps.gl_transaction.uri) <> 0.00 )
this is the LINQ i have managed to create so far, but i am struggling with the nested selects, the sum and the where clause
from acc in Accounts
join chart in Charts on acc.Chart_code equals chart.Code
join gltrans in Gl_transactions on acc.Uri equals gltrans.Account_uri
join debt in Debtors on gltrans.Debtor_uri equals debt.Uri
join recreg in Receivables_registers on gltrans.Receivables_register_uri equals recreg.Uri
join bankacc in Bank_accounts on recreg.Bank_account_uri equals bankacc.Uri
let paidcurrency = from gltrns in Gl_transactions
where gltrns.Sibling_uri == gltrans.Uri
select gltrns.Base_currency_amount
where
chart.Control_account == "Debtor"
&& gltrans.Status == "L"
&& gltrans.Process_status == "Released"
&& acc.Property_ref == 102979
&& ((gltrans.Generated == "C" && gltrans.Sibling_uri == null && gltrans.Written_off != "Y")
|| (gltrans.Generated == "N" && gltrans.Sibling_uri == null) )
select new
{
gltrans.Debtor_uri,
debt.Account_no,
gltrans.Uri,
gltrans.Base_currency_amount,
gltrans.Base_currency_vat_amount,
er = (decimal?)paidcurrency.Base_currency_vat_amount.Sum() ?? 0,
acc.Property_ref,
acc.Sub_ledger_code,
gltrans.Transaction_type_code,
gltrans.Transaction_description,
gltrans.Effective_date
}
This might help out a little. I blended in some fluent syntax to help translate the Sum functions. Let me know if some of these translations help as I can't check it directly without your schema and some data.
var result =
from acc in Accounts
join chart in Charts on acc.Chart_code equals chart.Code
join gltrans in Gl_transactions on acc.Uri equals gltrans.Account_uri
join debt in Debtors on gltrans.Debtor_uri equals debt.Uri
join recreg in Receivables_registers on gltrans.Receivables_register_uri equals recreg.Uri
join bankacc in Bank_accounts on recreg.Bank_account_uri equals bankacc.Uri
// query expression
//let paidcurrency = from gltrns in Gl_transactions
// where gltrns.Sibling_uri == gltrans.Uri
// select gltrns.Base_currency_amount
// change to fluent..
let paid_Amount = gltrans.Where(g => g.Sibling_uri == g.Uri)
.Select(g => g.Base_currency_amount * -1 ?? 0.00M).Sum()
// same for Vat..
let paid_Vat = gltrans.Where(g => g.Sibling_uri == g.Uri)
.Select(g => g.Base_currency_vat_amount * -1 ?? 0.00M).Sum()
// added another 'let' to use in the where clause..
let base_Currency = gltrans.Where(g => g.Sibling_uri == g.Uri)
.Select(g => g.Base_currenct_amount ?? 0.00M).Sum()
where
chart.Control_account == "Debtor"
&& gltrans.Status == "L"
&& gltrans.Process_status == "Released"
&& acc.Property_ref == 102979
&& (
(
gltrans.Generated == "C" &&
gltrans.Sibling_uri == null &&
gltrans.Written_off != "Y"
)
||
(
gltrans.Generated == "N" &&
gltrans.Sibling_uri == null
)
)
&& gltrans.Base_currency_amount + base_Currency != 0.00M
select new
{
gltrans.Debtor_uri,
debt.Account_no,
gltrans.Uri,
gltrans.Base_currency_amount,
gltrans.Base_currency_vat_amount,
//er = (decimal?)paidcurrency.Base_currency_vat_amount.Sum() ?? 0,
paid_Amount,
paid_Vat,
acc.Property_ref,
acc.Sub_ledger_code,
gltrans.Transaction_type_code,
gltrans.Transaction_description,
gltrans.Effective_date
};

LINQ SELECT TAKE 1 EACH ROW

How can i select take 1 each data in column in linq that only return 1 row. Because when i put .Take(1) only 1 row result will appear but i want to have 2 row result with different entry
to make it clear here's what i mean
in c# here's my query
using (PharmacyDBEntities entities = new PharmacyDBEntities())
{
var positem = (from a in entities.POSEntries.Take(1)
where a.Invoice.AccountID == authLogin.userid && a.Invoice.InvoiceStatusID == 1
select new
{
a.Item.ItemCode,
a.Item.Name,
Quantity = (from b in entities.POSEntries where b.Invoice.AccountID == authLogin.userid && b.Invoice.InvoiceStatusID == 1 select b).Count(),
a.Item.SellingPrice
}).ToList();
gcItemList.DataSource = positem;
}
And the result
Is there any suggestion guys? will make big help to me. thanks
You can use Linq GroupBy
var positem = entities.POSEntries.Where( a=> a.Invoice.AccountID == authLogin.userid && a.Invoice.InvoiceStatusID == 1)
.GroupBy(x=>x.Item.ItemCode).Select(g=> new {
g.Key,
g.First().Item.Name,
Quantity = g.Count(),
g.First().Item.SellingPrice
}).ToList();
So, you want Distinct() instead of Take(1)? Something along these lines:
var positem = (from a in entities.POSEntries
where a.Invoice.AccountID == authLogin.userid && a.Invoice.InvoiceStatusID == 1
select new
{
a.Item.ItemCode,
a.Item.Name,
Quantity = (from b in entities.POSEntries where b.Invoice.AccountID == authLogin.userid && b.Invoice.InvoiceStatusID == 1 select b).Count(),
a.Item.SellingPrice
}).Distinct().ToList();
Take only returns first n elements. I think you need to try using the Distinct method.

Get linq to return IEnumerable<DataRow> result

How can I convert following SQL query to LINQ in C#?
I don't need all columns from both tables and the result set should be
IEnumerable<DataRow>
Query:
select
c.level, cl.name, c.quantity
from
dbo.vw_categories c
left join
dbo.vw_categoriesLocalization cl on c.level = cl.level
and cl.language = 'en'
where
c.level like '000%'
and c.level <> '000';
Expected:
IEnumerable<DataRow> result = ????
Thanks in advance..
Here's how you would write the query:
var query =
from c in db.vw_categories
join cl in db.vw_categoriesLocalization on c.level equals cl.level into clo
from cl in clo.DefaultIfEmpty()
where (cl == null || cl.language == "en")
&& c.level.StartsWith("000")
&& c.level != "000"
select new
{
c.level,
name = cl == null ? null : cl.name,
c.quantity
}
To convert that to IEnumerable<DataRow> maybe you could do something like this:
var datarows = query.Select(r => {
var row = dataTable.NewRow();
row["level"] = r.level;
row["name"] = r.name;
row["quantity"] = r.quantity;
return row;
});
If using LINQ to SQL:
var ctx = new SomeDataContext();
from c in ctx.vw_categories
join cl in ctx.vw_categoriesLocation
on c.level equals cl.level into g
from clv in g.DefaultIfEmpty()
where (clv == null || clv.language == "en")
&& c.level.Contains("000%")
&& c.level != "000"
select new
{
c.level,
name = (clv != null) ? clv.name : default(string),
quantity = c.quantity
};
More info here: http://codingsense.wordpress.com/2009/03/08/left-join-right-join-using-linq/

Categories