How to use Exist sql function in Linq - c#

var _query = _dbContext.CashVoucherDetails
.Where(x => x.CreationDate.Date >= From.Date && x.CreationDate.Date <= To.Date && (x.Type == Common.TransactionType.CPV || x.Type == Common.TransactionType.BPV) && x.CompanyCode == BranchCode && x.DebitAmount > 0)
.GroupBy(v => new { v.AccountCode})
.Select(g => new
{
AccountCode = g.Key.AccountCode,
});
var balances = _dbContext.CashVoucherDetails
.Where(x => x.CreationDate.Date <= To.Date && x.CompanyCode == BranchCode)
//.Exist(_query.Account) (I want only account which exist in upper query)
.GroupBy(v => new { v.AccountCode})
.Select(g => new
{
AccountCode = g.Key.AccountCode,
Balance = g.Sum(x => x.DebitAmount - x.CreditAmount),
});
I want to use something like EXIST here in first query I have some specific accounts and in 2nd query I want to calculate balances of those accounts.
Can you please tell how I can use Exist function in LINQ.
Thank you.
I want this query to be implemented in LINQ:
SELECT `c`.`AccountCode`, `c`.`CompanyCode` AS `LocationCode`, COALESCE(SUM(`c`.`DebitAmount` - `c`.`CreditAmount`), 0) AS `Balance`
FROM `CashVoucherDetails` AS `c`
WHERE (CONVERT(`c`.`CreationDate`, date) <= '2022-12-20') AND (`c`.`CompanyCode` = '002') and `c`.`AccountCode` IN
(
SELECT `c`.`AccountCode`
FROM `CashVoucherDetails` AS `c`
WHERE ((((CONVERT(`c`.`CreationDate`, date) >= '2022-12-20') AND (CONVERT(`c`.`CreationDate`, date) <= '2022-12-20')) AND `c`.`Type` IN ('CPV', 'BPV')) AND (`c`.`CompanyCode` = '002')) AND (`c`.`DebitAmount` > 0)
GROUP BY `c`.`AccountCode`
)
GROUP BY `c`.`AccountCode`, `c`.`CompanyCode`;

you can use Contains or Any.
_dbContext.CashVoucherDetails
.Where(x => x.CreationDate.Date <= To.Date && x.CompanyCode == BranchCode)
.Where(x => _query.Select(q => q.AccountCode).Contains(x.AccountCode))
Or
.Where(x => _query.Any(q => q.AccountCode == x.AccountCode))

Maybe something like that
var balances = _dbContext.CashVoucherDetails
.Where(x => x.CreationDate.Date <= To.Date && x.CompanyCode == BranchCode && _query.Any(q => q.AccountCode == x.AccountCode))
.GroupBy(v => new { v.AccountCode})
.Select(g => new
{
AccountCode = g.Key.AccountCode,
Balance = g.Sum(x => x.DebitAmount - x.CreditAmount),
});

Related

EF core Get Count and sum in one call

Using Entity Framework core, can I get the total sum of the column and row count in one call?
I have the following code, but I think there is a better way to do this.
TotalCostResponse result = new TotalCostResponse
{
TotalCost = await dbContext.Transaction
.Where(x => x.UserName == request.UserName
&& x.Date >= request.StartDate
&& x.Date <= request.EndDate)
.SumAsync(x => x.Amount),
TotalNumber = await dbContext.Transaction
.Where(x => x.UserName == request.UserName
&& x.Date = request.StartDate
&& x.Date <= request.EndDate)
.CountAsync()
};
So instead of calling dbContext two times, I need to make it in one call.
var result = await dbContext.Transaction
.Where(x => x.UserName == request.UserName
&& x.Date >= request.StartDate
&& x.Date <= request.EndDate)
.GroupBy(x => 1)
.Select(group => new TotalCostResponse
{
TotalCost = group.Sum(x => x.Amount),
TotalNumber = group.Count()
})
.FirstOrDefaultAsync();
Here is an example with one query, there are certainly other ways that you can find.
// In the select get only what you need, in your case only the amount
var transactions =
await this.dbContext.Transaction
.Where(x => x.UserName == request.UserName
&& x.Date >= request.StartDate
&& x.Date <= request.EndDate)
.Select(y => new
{
Amount = y.Amount,
}).ToListAsync();
// Calculating the data
var result = new TotalCostResponse
{
TotalCost = transactions.Sum(x => x),
TotalNumber = transactions.Count(),
}

How to improve this C# Linq Concat Example?

The following C# Linq example displays the correct records in a serverSide datatable. However, when I add the following line: data = data.Concat(unconfirmed);, it increases the page/datatable load time from ~500 ms to ~2 seconds when year equals the current year. Searching by the current year displays the most amount of records, but they are only ~90. Searching by a previous year displays ~10 records at most and it only takes ~500 ms for the page/datatable to load:
var data = _db.ResidencyConfirmations.AsQueryable();
var year = Request.Form.GetValues("columns[11][search][value]")[0];
var showConfirmed = Request.Form.GetValues("columns[12][search][value]")[0];
int.TryParse(year, out var resultYear);
data = data.Where(rc => rc.Application.ApplicationType.Label == "Home Rehab");
var allNotesReleased = data.Where(rc => rc.Application.ApplicationActivityPhas
.Where(aap => aap.ActivityPhas.WorkFlowStep == 6)
.Select(aap => aap.ActivityPhas.ActivityPhase)
.FirstOrDefault() == "All Notes Released" &&
rc.Application.ApplicationActivityPhas
.Where(aap => aap.ActivityPhas.WorkFlowStep == 6)
.Select(aap => aap.ActivityPhaseDate)
.FirstOrDefault().Year >= resultYear);
var complete = data.Where(rc => rc.Application.ApplicationActivityPhas
.Where(aap => aap.ActivityPhas.WorkFlowStep == rc.Application.ApplicationActivityPhas
.Max(x => x.ActivityPhas.WorkFlowStep))
.Select(aap => aap.ActivityPhas.ActivityPhase)
.FirstOrDefault() == "Complete" &&
rc.Application.ApplicationActivityPhas
.Where(aap => aap.ActivityPhas.WorkFlowStep == 5)
.Select(aap => aap.ActivityPhaseDate)
.FirstOrDefault().Year < resultYear);
var unconfirmed = complete.Where(rc => !rc.Application.ResidencyConfirmations
.Any(x => x.ResidencyConfirmationDate.Year == resultYear))
.GroupBy(rc => rc.Application.AppNumber)
.Select(rc => rc.OrderByDescending(x => x.ResidencyConfirmationDate)
.FirstOrDefault());
data = allNotesReleased.Concat(complete)
.Where(rc => rc.ResidencyConfirmationDate.Year == resultYear);
if (showConfirmed == "false")
data = data.Where(rc => !rc.Deed || !rc.Utility || !rc.VitalRecords);
data = data.Concat(unconfirmed);
Not sure how it compiles, written in text editor, but query should be faster. Note that instead of using .Year introduced range variables, it will speedup query if you have indexes on date.
var year = Request.Form.GetValues("columns[11][search][value]")[0];
var showConfirmed = Request.Form.GetValues("columns[12][search][value]")[0];
int.TryParse(year, out var resultYear);
var startOfTheYear = new DateTime(resultYear, 1, 1);
var nextYear = startOfTheYear.AddYears(1);
var data = _db.ResidencyConfirmations.AsQueryable();
data = data.Where(rc => rc.Application.ApplicationType.Label == "Home Rehab");
var allNotesReleased =
from rc in data
from aap in rc.Application.ApplicationActivityPhas
.Where(aap => aap.ActivityPhas.WorkFlowStep == 6)
.Take(1)
where
aap.ActivityPhas.ActivityPhase == "All Notes Released" &&
app.ActivityPhaseDate >= startOfTheYear &&
rc.ResidencyConfirmationDate >= startOfTheYear && rc.ResidencyConfirmationDate < nextYear
select rc;
var complete =
from rc in data
from aap in rc.Application.ApplicationActivityPhas
.OrderByDescending(aap => aap.WorkFlowStep)
.Take(1)
from aap2 in rc.Application.ApplicationActivityPhas
.Where(aap2 => aap2.ActivityPhas.WorkFlowStep == 5)
.Take(1)
where
aap.ActivityPhas.ActivityPhase == "Complete" &&
app2.ActivityPhaseDate < startOfTheYear &&
rc.ResidencyConfirmationDate >= startOfTheYear && rc.ResidencyConfirmationDate < nextYear
select rc;
var unconfirmed = complete
.Where(rc => !rc.Application.ResidencyConfirmations
.Any(x => x.ResidencyConfirmationDate >= startOfTheYear && x.ResidencyConfirmationDate < nextYear)
)
.GroupBy(rc => rc.Application.AppNumber)
.Select(rc => rc
.OrderByDescending(x => x.ResidencyConfirmationDate)
.First()
);
if (showConfirmed == "false")
data = data.Where(rc => !rc.Deed || !rc.Utility || !rc.VitalRecords);
data = data.Concat(unconfirmed);
To improve performance and to display the correct records, I made the following changes/additions:
if (resultYear == DateTime.Now.Year)
data = data.Where(rc => rc.Application.ApplicationType.Label == "Home Rehab")
.GroupBy(rc => rc.Application.AppNumber)
.Select(rc => rc.OrderByDescending(x => x.ResidencyConfirmationDate)
.FirstOrDefault());
else
data = data.Where(rc => rc.Application.ApplicationType.Label == "Home Rehab");
IQueryable<ResidencyConfirmation> unconfirmed = null;
if (resultYear == DateTime.Now.Year)
unconfirmed = complete.Where(rc => !rc.Application.ResidencyConfirmations
.Any(x => x.ResidencyConfirmationDate.Year == resultYear));
else
unconfirmed = complete.Where(rc => !rc.Application.ResidencyConfirmations
.Any(x => x.ResidencyConfirmationDate.Year == resultYear))
.GroupBy(rc => rc.Application.AppNumber)
.Select(rc => rc.OrderByDescending(x => x.ResidencyConfirmationDate)
.FirstOrDefault());
It now takes right under 1 second for the page/datatable to load.

optimize query with lambra expression in entity framework

I have the following query, often have excution timeout errors, have any ideas for optimization.
Thank you!
queryResult = db.Products
.Where(x => !x.product_is_deleted)
.Where(x => x.product_name.Contains(keyword) || x.product_barcode.Contains(keyword) || x.ProductType.pro_type_name.Contains(keyword) || x.ProductType.pro_type_name.Contains(keyword))
.Select(x => new ProductView
{
product_id = x.product_id,
product_barcode = x.product_barcode,
product_name = x.product_name,
product_unit = x.product_unit,
product_size = x.product_size,
product_weight = x.product_weight,
product_type_id = x.product_type_id,
product_inventory = shelf == 0 ? (x.ImportProductDetails.Where(y => y.imp_pro_detail_product_id == x.product_id && y.ImportProduct.import_pro_warehouse_id == warehouse_id ).Select(y => y.imp_pro_detail_inventory).DefaultIfEmpty(0).Sum()) : (x.ImportProductDetails.Where(y => y.imp_pro_detail_product_id == x.product_id && y.ImportProduct.import_pro_warehouse_id == warehouse_id && y.imp_pro_detail_shelf_id == shelf).Select(y => y.imp_pro_detail_inventory).DefaultIfEmpty(0).Sum()),
product_opening_stock = x.product_opening_stock,
product_type_name = x.ProductType.pro_type_name,
product_price = x.ProductPrices.Where(y => !y.proprice_is_deleted).Where(y => y.proprice_applied_datetime <= DateTime.Now).OrderByDescending(y => y.proprice_applied_datetime).Select(y => y.proprice_price).FirstOrDefault(),
product_discount_type = x.ProductDiscounts.Where(y => !y.pro_discount_is_deleted && y.pro_discount_start_datetime <= datetimeNow && y.pro_discount_end_datetime >= datetimeNow).OrderByDescending(y => y.pro_discount_id).Select(y => y.pro_discount_type).FirstOrDefault(),
product_discount_value = x.ProductDiscounts.Where(y => !y.pro_discount_is_deleted && y.pro_discount_start_datetime <= datetimeNow && y.pro_discount_end_datetime >= datetimeNow).OrderByDescending(y => y.pro_discount_id).Select(y => y.pro_discount_value).FirstOrDefault()
//product_norm_name = x.ProductionNorms.Where(y => y.pro_norm_name == x.product_id && y.pro_norm_is_applied == true).Select(y => y.pro_norm_id).FirstOrDefault()
});

Can my two linq lines of code be combined?

I'm not sure how to do this since I'm only familiar with the basic form or Linq.
Here are my two sets of code:
var qry = from x in CustomersChecks.CustomersChecksList
where x.RoutingNumber == routingnumber &&
x.BankAccountNumber == bankAccountNumber &&
x.Branch > 0 &&
x.AccountNumber > 0
orderby x.Name
select x;
var qry2 = qry.GroupBy(x => new { x.Branch, x.AccountNumber}).Select(x => x.First()).ToList();
Ultimately, I want to get my first query in order of Branch + Account Number distinctly.
Can they be combined or is what I have the only way to do this?
The quick and dirty solution is just to add the GroupBy chain to the end of the first query.
var qry = (from x in CustomersChecks.CustomersChecksList
where x.RoutingNumber == routingnumber &&
x.BankAccountNumber == bankAccountNumber &&
x.Branch > 0 &&
x.AccountNumber > 0
orderby x.Name
select x).GroupBy(x => new { x.Branch, x.AccountNumber})
.Select(x => x.First())
.ToList();
Or do the following by incorrupating the group by into the exist query syntax
var qry = (from x in CustomersChecks.CustomersChecksList
where x.RoutingNumber == routingnumber &&
x.BankAccountNumber == bankAccountNumber &&
x.Branch > 0 &&
x.AccountNumber > 0
orderby x.Name
group x by new { x.Branch, x.AccountNumber} into grp
select grp.First()).ToList();
var qry = CustomersChecks.CustomersChecksList.Where(x =>
x.RoutingNumber == routingnumber &&
x.BankAccountNumber == bankAccountNumber &&
x.Branch > 0 &&
x.AccountNumber > 0).OrderBy(x => x.Name)
.GroupBy(x => new { x.Branch, x.AccountNumber})
.Select(x => x.First())
.ToList();

Linq return first date

I have the query:
var q = db.tblArcadeGamePlays
.Where(c => c.GameID == GameID && c.ReferalID != 0 && c.ReferalID != null)
.GroupBy(r => new { r.ReferalID })
.Select(g => new { Plays = g.Count(), URL = g.Key.ReferalID })
;
tblArcadeGamePlays also has a field Date, in the group I'd like to return the earliest observed date that group contains.
How would I do this?
.Select(g => new {
Plays = g.Count(), URL = g.Key.ReferalID,
MinDate = g.Min(x => x.Date
});
you might also find the LINQ syntax easier to read/maintain here, but... the extension syntax will work too. But as LINQ:
var q = from c in db.tblArcadeGamePlays
where c.GameID == GameID && c.ReferalID != 0 && c.ReferalID != null
group c by c.ReferalID into g
select new {
Plays = g.Count(), URL = g.Key.ReferalID, MinDate = g.Min(x=>x.Date)
};
this might work
var firstIndex = q.Min(c => c.Date);
var q = db.tblArcadeGamePlays .Where(c => c.GameID == GameID && c.ReferalID != 0 && c.ReferalID != null) .GroupBy(r => new { r.ReferalID }) .Select(g => new { Plays = g.Count(), URL = g.Key.ReferalID , Date = g.Min(cc=>cc.DateField) }) ;
Replace DateField with your actual property

Categories