assistance required to convert SQL into LINQ - c#

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
};

Related

Change SQL Query to LINQ, asp.net MVC

How to change this SQL query to LINQ? I've tried it several times, but it didn't work
SELECT Payment.ID, Payment.TotalGroupID, PaymentTrans.PaymentID, PaymentTrans.TotalGroupID as TotalGroupID1, PaymentTrans.TransferStatus
FROM PaymentTrans INNER JOIN Payment
ON (PaymentTrans.PaymentID = Payment.ID OR PaymentTrans.TotalGroupID = payment.TotalGroupID)
WHERE (PaymentTrans.TransferStatusis NULL OR (PaymentTrans.TransferStatus <> '01' and PaymentTrans.TransferStatus <> '02'))
and this is my try
var a= (from x in db.PaymentTransactions
join p in db.Payments
on
x.PaymentID equals p.ID
where x.TransferStatus== null || (x.TransferStatus!= "01" && x.TransferStatus!= "02")
select new { x, p }).ToList();
but it still wrong LINQ, because in my query I have 2 conditions in ON Clause. thanks
try this
var query = (from x in db.PaymentTransactions
join p in db.Payments
on x.PaymentID equals p.ID //main condition of join
where ((x.TransferStatus == null ||
(x.TransferStatus != "01" && x.TransferStatus!= "02")) //your `where` condition
|| x.TotalGroupID == p.TotalGroupID) //your second or join
select new {x,p})
.ToList();
The answers above filter on both conditions, they should filter one of the conditions according to the question (PaymentID or TotalPaymentID). You can either write two seperate queries and use a union or use a Cartesian product before filtering.
var result = (from paymentTransaction in db.PaymentTransactions
join payment in db.Payments on paymentTransaction.PaymentID equals payment.ID
where paymentTransaction.TransferStatus == null || (paymentTransaction.TransferStatus != "01" && paymentTransaction.TransferStatus != "02")
select new { paymentTransaction, payment }).Union
(from paymentTransaction in db.PaymentTransactions
join payment in db.Payments on paymentTransaction.TotalGroupID equals payment.TotalGroupID
where paymentTransaction.TransferStatus == null || (paymentTransaction.TransferStatus != "01" && paymentTransaction.TransferStatus != "02")
select new { paymentTransaction, payment });
var cartResult = from paymentTransaction in db.PaymentTransactions
from payment in db.Payments
where paymentTransaction.PaymentID == payment.ID || paymentTransaction.TotalGroupID == payment.TotalGroupID
where paymentTransaction.TransferStatus == null || (paymentTransaction.TransferStatus != "01" && paymentTransaction.TransferStatus != "02")
select new { paymentTransaction, payment };
You cannot add multiple ON in LINQ. the solution of your problem above can be solved like this.
Hint: just use multiple Where.
var result =
(
from trans in db.PaymentTransactions
join payment in db.payments
on trans.PaymentID equals payment.ID
where trans.TotalGroupID == payment.TotalGroupID
where x.TransferStatus== null || (x.TransferStatus!= "01" && x.TransferStatus!= "02")
select new
{
//your properties
}
).ToList();

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();
?

SQL to LINQ - multiple tables left outer join with where clause referring right table

I have this following query and want to convert to LINQ.
I have tried LINQPad and Linqer but getting an error in Visual Studio.
SELECT DISTINCT
g.TXT_Property,
up.TXT_Page
FROM MD g
LEFT JOIN MD ux ON ux.TXT_Page = #sPage
AND ux.TXT_Property = g.TXT_Property
AND ux.TXT_Product = #sProdAll
AND ux.GID_Section IS NULL
LEFT JOIN MD up ON up.TXT_Page = #sPage
AND up.TXT_Property = g.TXT_Property
AND (ISNULL(up.TXT_Product, '') = #sProd or up.TXT_Product = #sProdAlt)
AND up.GID_Section IS NULL
WHERE
(g.GID_Section IS NULL)
AND g.TXT_Page = #sPage
and (ISNULL(g.TXT_Product, '') = #sProd or g.TXT_Product = #sProdAlt or g.TXT_Product = #sProdAll)
ORDER BY TXT_Property, TXT_Product, TXT_Language
This what I have tried:
var query2 = from g in list
join ux in list
on g.Property equals ux.Property into g_ux
where ux.Page == sPage
&& ux.Product == sProdAll
&& ux.Section == null
And this is another try.
I have referred to
SQL to LINQ - multiple tables left outer join with where clause referring right table
// Another query
var query = (from g in
((from d in list
where ((d.Section == null || d.Section == uSection) && (d.Product == sProd || (sProd == "" && d.Product == null) || (d.Product == sProdAlt) || (d.Product == sProdAll)))
select (new { d.Property })).ToList())
join gx in
((from d in list
where (d.Section == null) && (d.Product == sProdAll)
select (new { d.Property, d.Page, d.Product, d.Language, d.Value, d.Section })).ToList())
on g.Property equals gx.Property into res1
from a1 in res1.DefaultIfEmpty()
join gp in
((from d in list
where (d.Section == null) && (d.Product == sProd || (sProd == "" && d.Product == null) || (d.Product == sProdAlt))
select (new { d.Property, d.Page, d.Product, d.Language, d.Value, d.Section })).ToList())
on g.Property equals gp.Property into res2
from a2 in res2.DefaultIfEmpty()
join ux in
((from d in list
where (d.Section == uSection) && (d.Product == sProdAll)
select (new { d.Property, d.Page, d.Product, d.Language, d.Value, d.Section })).ToList())
on g.Property equals ux.Property into res3
from a3 in res3.DefaultIfEmpty()
join up in
((from d in list
where (d.Section == uSection) && (d.Product == sProd || (sProd == "" && d.Product == null) || (d.Product == sProdAlt))
select (new { d.Property, d.Page, d.Product, d.Language, d.Value, d.Section })).ToList())
on g.Property equals up.Property into res4
from a4 in res4.DefaultIfEmpty()
orderby (new
{
TXT_Property = g.Property,
TXT_Product = Coalesce((Coalesce(a4.Page, "") == "" ? Coalesce(a4.Product, a3.Product) : Coalesce(a4.Product, "SA")), a3.Product, (Coalesce(a2.Page, "") == "" ? Coalesce(a2.Product, a1.Product) : Coalesce(a2.Product, "SA")), a1.Product),
TXT_Language = Coalesce(a4.Language, a3.Language, a2.Language, a1.Language),
})
select (new
{
TXT_Property = g.Property,
TXT_Product = Coalesce((Coalesce(a4.Page, "") == "" ? Coalesce(a4.Product, a3.Product) : Coalesce(a4.Product, "SA")), a3.Product, (Coalesce(a2.Page, "") == "" ? Coalesce(a2.Product, a1.Product) : Coalesce(a2.Product, "SA")), a1.Product),
TXT_Language = Coalesce(a4.Language, a3.Language, a2.Language, a1.Language),
TXT_Value = Coalesce(a4.Value, a3.Value, a2.Value, a1.Value)
}));
Your SQL query seems very questionable to me (since ux is a LEFT JOIN and (presumably) not referenced in the rest of the query, it adds nothing), and I had to assume the ORDER BY was on the g columns since it wasn't specified (and I am surprised that isn't rejected by SQL as ambiguous), but here is my try at the translation:
var ans = from g in MD
join ux in MD on new { TXT_Page = sPage, g.TXT_Property, TXT_Product = sProdAll, GID_Section = (string)null } equals new { ux.TXT_Page, ux.TXT_Property, ux.TXT_Product, ux.GID_Section } into uxj
from ux in uxj.DefaultIfEmpty()
join up in MD on new { TXT_Page = sPage, g.TXT_Property, GID_Section = (string)null } equals new { up.TXT_Page, up.TXT_Property, up.GID_Section } into upj
from up in upj.DefaultIfEmpty()
where up == null || (up.TXT_Product ?? "") == sProd || up.TXT_Product == sProdAlt
where g.GID_Section == null && g.TXT_Page == sPage &&
((g.TXT_Product ?? "") == sProd || g.TXT_Product == sProdAlt || g.TXT_Product == sProdAll)
orderby g.TXT_Property, g.TXT_Product, g.TXT_Language
select new { g.TXT_Property, up.TXT_Page };
Note: I put in the up == null because because otherwise the where might reject where the LEFT JOIN in SQL wouldn't.
I assumed the type of GID_Section was string, but you can cast the nulls to the right type.
Here is my SQL conversion recipe, though your SQL was a bit trickier since it combined LEFT JOIN and non-equijoin.
For translating SQL to LINQ query comprehension:
Translate FROM subselects as separately declared variables.
Translate each clause in LINQ clause order, translating monadic and aggregate operators (DISTINCT, TOP, MIN, MAX etc) into functions applied to the whole LINQ query.
Use table aliases as range variables. Use column aliases as anonymous type field names.
Use anonymous types (new { ... }) for multiple columns.
JOIN conditions that aren't all equality tests with AND must be handled using where clauses outside the join, or with cross product (from ... from ...) and then where
JOIN conditions that are multiple ANDed equality tests between the two tables should be translated into anonymous objects
LEFT JOIN is simulated by using into joinvariable and doing another from from the joinvariable followed by .DefaultIfEmpty().
Replace COALESCE with the conditional operator (?:)and a null test.
Translate IN to .Contains() and NOT IN to !...Contains(), using literal arrays or array variables for constant lists.
Translate x BETWEEN low AND high to low <= x && x <= high.
Translate CASE to the ternary conditional operator ?:.
SELECT * must be replaced with select range_variable or for joins, an anonymous object containing all the range variables.
SELECT fields must be replaced with select new { ... } creating an anonymous object with all the desired fields or expressions.
Proper FULL OUTER JOIN must be handled with an extension method.

linq using IN Operator in split comma values

I am getting the following results for
string[] proj = Pid.Split(',');
"1032,1222" --> [0]=1032,[1]=1222
but I want to use in LINQ query. This is my LINQ query. Where to use it and how to use it?
string[] proj = Pid.Split(',');
var data2 = (from p in Db.emp.AsEnumerable()
join r in Db.use on p.EmployeeId equals r.EmployeeId
join q in Db.proo on p.EmployeeId equals q.EmpId
where (q.IsDelete == false && p.IsDelete == false && p.RoleID != 1 && p.RoleID != 2 && q.ProId == Convert.ToInt32(Pid))
select new GroupSelectedModel {
Text = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(p.FirstName + " " + p.LastName),
Value = r.UserId.ToString(),
StatusId = Convert.ToInt32(p.Status)
})
.Distinct().ToList().OrderBy(r => r.Text);
return data2.OrderBy(p => p.StatusId).ToList();
Please check above mentioned code.
When you need IN, you have to invert it, and use Contains(). Your post is not very clear, but I think you're asking for something like this (note you need to use a List instead of an array):
List<string> proj = new List<string>(Pid.Split(','));
where (q.IsDelete == false && p.IsDelete == false && p.RoleID != 1 && p.RoleID != 2 && proj.Contains(q.ProId))

LINQ2SQL Any(), NOT EXISTS Problems

I have a problem with my linq2sql while grabbing rows from database by condition select n rows from table1 where table2 doesn't contain any rows by condition table1.id != table2.accId and table1.action != "action_constant" i have such a code in my c#:
query = (from accsArray in db.Accs
where accsArray.Valid == 1 &&
!String.IsNullOrEmpty(accsArray.Password) &&
accsArray.vip_rec == 0 || accsArray.data_col == null &&
!db.Reaktors.Any(rk => rk.Action == action &&
rk.Account_id == accsArray.id)
select new DbAcc
{
id = accsArray.id,
Login = accsArray.Login,
Password = accsArray.Password,
System = accsArray.System,
//FriendsCount = Convert.ToInt32(accsArray.Friends_count)
}).Take(count).OrderBy(acc => acc.id);
!db.Reaktors.Any(rk => rk.Action == action && rk.Account_id == accsArray.id) this doesn't work, while looking for my clean sql code i see this:
SELECT [t2].[id], [t2].[Login], [t2].[System], [t2].[Password]
FROM (SELECT TOP (50) [t0].[id], [t0].[Login], [t0].[System], [t0].[Password]
FROM [Collider].[dbo].[Accs] AS [t0]
WHERE (([t0].[Valid] = 1)
AND ([t0].[Password] <> '')
AND ([t0].[Login] <> '')
AND ([t0].[data_col] = 0))
OR (([t0].[data_col] IS NULL)
AND (NOT (EXISTS(SELECT NULL AS [EMPTY]
FROM [dbo].[Reaktor] AS [t1]
WHERE [t1].[Actionself] = '_take_acc_dc'
AND ([t1].[Account_id] = [t0].[id])))))) AS [t2]
ORDER BY [t2].[id]
I'm afraid of SELECT NULL AS [EMPTY] FROM [dbo].[Reaktor] especially of NULL AS [EMPTY] so i think that's why it doesn't work correctly.
The solution is to place paranthesis right and to order conditions. The good working code will look like this:
query = (from accsArray in db.Accs
where !db.Reaktors.Any(rk => (rk.Actionself == action
&& rk.Account_id == accsArray.id))
&& accsArray.Valid == 1
&& accsArray.Password != String.Empty
&& accsArray.Login != String.Empty
&& accsArray.data_col == 0
select new DbAcc
{
id = accsArray.id,
Login = accsArray.Login,
Password = accsArray.Password,
System = accsArray.System,
}).Take(count).OrderBy(acc => acc.id);

Categories