when i tried to group by IQueryable i found that query was very very slowly
and when i removed group by it return fast
can any one help me
public async Task<GridOutPut<ticketSearchRes>> ticketGridView<T>(GridViewEntity gridViewInputsVM, gridViewSearch searchRes , int CurrentuserId)
{
List<ticketSearchRes> tickets = new List<ticketSearchRes>();
IQueryable<ticketSearchRes> source = (from ticket in _db.TblTicket
join ticketCycle in _db.TblTicketCycle on ticket.TicketId equals ticketCycle.TicketId where ticketCycle.IsVisable == 1
join ticketUser in _db.TblTicketUser on ticket.TicketId equals ticketUser.TicketId
where ticketUser.UserId == CurrentuserId || (ticketUser.UserId != CurrentuserId && ticket.CreatedBy == CurrentuserId)
group ticket by new { ticket.TicketId } into groupedTickets // grouped by here
select new ticketSearchRes
{
title = (groupedTickets.FirstOrDefault().TicketTitle != null) ? groupedTickets.FirstOrDefault().TicketTitle.ToString() : "",
ticId = groupedTickets.FirstOrDefault().ToString(),
encTicId = (groupedTickets.FirstOrDefault().TicketId.ToString() != null) ? groupedTickets.FirstOrDefault().TicketId.ToString() : "",
createdBy = (groupedTickets.FirstOrDefault().CreatedBy.ToString() != null) ? groupedTickets.FirstOrDefault().CreatedBy.ToString() : "",
}
).AsQueryable();
if (searchRes.title != "") // ticket title search for ID || Title || Description
{
source = source.Where(a => a.title.ToLower().Trim().Contains(searchRes.title) || a.description.ToLower().Trim().Contains(searchRes.title) || a.ticId.ToLower().Trim().Contains(searchRes.title));
}
if (searchRes.ticStatus != 0) { // ticket status
source = source.Where(a => a.status == searchRes.ticStatus.ToString());
}
if (searchRes.ticCategory != 0) // ticket category
{
source = source.Where(a => a.categoryId == searchRes.ticCategory.ToString());
}
return await source.SortFunctionAsync(tickets, gridViewInputsVM);
}
Related
I configured hangfire to run 2 cron jobs. In the recurring jobs tab I can see the jobs and the next run time is correct but I have received over 15 emails that are triggered by the function hangfire is calling and I can't see the history of those calls on the succeeded jobs tab on hangfire. I want the function to be called once everyday. PS: there is just one server showing on hangfire
```recurringJobManager.AddOrUpdate("RecurringDeposits", () => serviceProvider.GetService<IRecurringDeposits>().AutomatedDepositsAsync(), Cron.Daily(8, 0));
recurringJobManager.AddOrUpdate("RecurringWithdrawals", () => serviceProvider.GetService<IRecurringWithdrawals>().AutomatedWithdrawalsAsync(), ```
the function
```public async Task AutomatedDepositsAsync()
{
var coreAccounts = await _dbContext.CustomerAccounts
.Include(x => x.Customer)
.Where(x => x.IsActive
&& (x.Product.Code == coreAccountCode || x.Product.Code == privateGroupCode || x.Product.Code == publicGroupCode || x.Product.Code == myPurseAccountCode)
&& x.RecurringCredit && x.CreditInterval != 0 && x.PlanEndDate == null)
.ToListAsync();
if(coreAccounts != null)
{
foreach (var acct in coreAccounts)
{
var firstTran = await _dbContext.xxx
.Where(x => x.IsApproved
&& x.Channel == "Card" && x.AccountId == xx.Id)
.OrderBy(x => x.IsApprovedDate)
.FirstOrDefaultAsync();
var card = _dbContext.CustomerCards
.Where(x => x.UserId == acct.Customer.Id && x.IsDeleted == false)
.OrderBy(x => x.CreationTime)
.LastOrDefault();
if (card==null)
{
continue;
}
if (acct.CreditInterval == 1 && DateTime.UtcNow.Date > firstTran.IsApprovedDate)
{
await DebitCustomerCard(firstTran, acct.Customer.Email, acct, card);
}
else if (acct.CreditInterval == 7)
{
var firstDepositDate = firstTran.IsApprovedDate;
var firstDepositDay = firstDepositDate.Value.DayOfWeek;
var Today = DateTime.UtcNow.DayOfWeek;
if(DateTime.UtcNow.Date > firstDepositDate && firstDepositDay == Today)
{
await DebitCustomerCard(firstTran, acct.Customer.Email, acct, card);
}
}
else if (acct.CreditInterval == 30)
{
var firstDepositDate = firstTran.IsApprovedDate;
var firstDepositDay = firstDepositDate.Value.Day;
var currentMonth = DateTime.UtcNow.Month;
var currentyear = DateTime.UtcNow.Year;
CultureInfo provider = CultureInfo.InvariantCulture;
var NextDepositDate = DateTime.ParseExact(firstDepositDay + "/" + currentMonth + "/" + currentyear, "dd/MM/yyyy", provider);
if(DateTime.UtcNow.Date > firstDepositDate && DateTime.UtcNow.Date == NextDepositDate.Date)
{
await DebitCustomerCard(firstTran, acct.Customer.Email, acct, card);
}
}
}
}
}
public async Task DebitCustomerCard(CustomerContribution firstTransaction, string custEmail, CustomerAccount custAcct, CustomerCard Card)
{
var contribution = await _dbContext.Contributions.AddAsync(new CustomerContribution
{
Account = firstTransaction.Account,
Amount = firstTransaction.Amount,
Tenor = firstTransaction.Tenor,
Rate = firstTransaction.Rate,
ExpectedReturn = firstTransaction.ExpectedReturn,
ChannelCode = Card.AuthCode,
Channel = "Card",
});
await _dbContext.SaveChangesAsync();
if (contribution == null)
{
//do something
return;
}
var reference = $"CRD-{DateTime.UtcNow:yyyyMMddHHmmssffff}{Utils.GenerateRandomString(4)}";
var transactionLog = new TransactionLog
{
Account = firstTransaction.Account,
Amount = firstTransaction.Amount,
TransactionDate = DateTime.UtcNow,
Type = TransactionType.SingleDebit,
Reference = reference,
Narration = "Automatic Deposit"
};
await _dbContext.TransactionLogs.AddAsync(transactionLog);
await _dbContext.SaveChangesAsync();
var postingResponse = await _postingService
.ChargeCustomerAccount(new xxxxx.ChargeCustomerRequest
{
Amount = firstTransaction.Amount,
AuthCode = Card.AuthCode,
Email = custEmail,
Reference = reference
});
if (postingResponse.OperationResult != OperationResult.Success)
{
//do something
return;
}
transactionLog.ExtReference = postingResponse.Data?.Reference;
transactionLog.Status = postingResponse.OperationResult.ToString();
_dbContext.TransactionLogs.Update(transactionLog);
custAcct.AvailableBalance += firstTransaction.Amount;
custAcct.TotBalance += firstTransaction.Amount;
custAcct.TotDeposit += firstTransaction.Amount;
_dbContext.CustomerAccounts.Update(custAcct);
contribution.Entity.IsApproved = true;
contribution.Entity.IsApprovedDate = DateTime.UtcNow;
_dbContext.Contributions.Update(contribution.Entity);
await _dbContext.SaveChangesAsync();
}
```
src/resolver/record/record.query.ts should be able to not pass company id for user that are authUser.isSuperuser
this will not work as expected.
Please do not search for the company in the first place if no company was passed.
with this change it would do the following query:
r.name ILIKE "" OR r.company = null AND (r.secure = false OR r.author = 123)
-> showing all records that match the name search OR where the user has access
public async search(
company: CompanyEntity,
query: string,
start: number = 0,
limit: number = 50,
user: UserEntity = null,
filter: RecordPagerFilterInputModel = null
): Promise<[RecordEntity[], number]> {
const qb = this.recordRepository
.createQueryBuilder('r')
.where('r.meetingRecord IS NULL')
.andWhere('r.name ILIKE ""')
.orWhere('r.company = null')
.andWhere('(r.secure = false OR r.author = 123)')
.setParameters({
query: `%${query}%`,
company: company.id,
secure: false,
author: user ? user.id : -1,
})
.orderBy('r.created', 'DESC')
console.log('qb',qb.getQuery())
if (filter && filter.secure !== undefined) {
qb.andWhere('r.secure = :filterSecure', { filterSecure: filter.secure })
}
if (filter && filter.own !== undefined) {
qb.andWhere(filter.own ? 'r.author = :author' : 'r.author <> :author')
}
if (filter && filter.language !== undefined) {
qb.andWhere('r.language = :filterLanguage', { filterLanguage: filter.language })
}
if (filter && filter.status !== undefined) {
qb.andWhere('r.status IN (:...filterStatus)', { filterStatus: filter.status })
}
qb.skip(start)
qb.take(limit)
return await qb.getManyAndCount()
}
you should use () in all orWhere:
.orWhere(((r.name ILIKE "" OR r.company = null) AND (r.secure = false OR r.author = 123)))
link look like http://localhost/index.php?page=search&sOrder=dt_pub_date&iOrderType=desc&sPattern=car
// AJAX SEARCH
$('body#body-search').on('change click', '.link-check-box a, .filter-remove a, form.search-side-form input:not(.term), body#body-search #sub-nav a, #home-cat a, #sub-cat a, form.search-side-form select, .sort-it a, .user-type a,.list-grid a, .paginate a', function(event) {
var ajaxStop = false;
if(ajaxSearch == 1 && event.type != 'change') {
event.preventDefault();
}
// Disable on mobile devices when input selected from fancybox
if($(event.target).closest('.search-mobile-filter-box').length) {
if(!$(event.target).closest('#search-sort').length && !$(event.target).closest('.sub-line').length) { // it may not be required
var ajaxStop = true;
//return false;
}
}
var sidebarReload = true;
if($(this).closest('.sidebar-hooks').length || $(event.target).attr('name') == 'locUpdate') {
sidebarReload = false;
}
var sidebar = $('.filter form.search-side-form');
var ajaxSearchUrl = '';
if (event.type == 'click') {
if(typeof $(this).attr('href') !== typeof undefined && $(this).attr('href') !== false) {
ajaxSearchUrl = $(this).attr('href');
}
} else if (event.type == 'change') {
ajaxSearchUrl = baseDir + "index.php?" + sidebar.find(':input[value!=""]').serialize();
}
if(ajaxSearch == 1 && $('input[name="ajaxRun"]').val() != "1" && (ajaxSearchUrl != '#' && ajaxSearchUrl != '') && !ajaxStop) {
if(ajaxSearchUrl == $(location).attr('href')) {
return false;
}
sidebar.find('.init-search').addClass('btn-loading').addClass('disabled').attr('disabled', true);
sidebar.find('input[name="ajaxRun"]').val("1");
$('#search-items').addClass('loading');
$.ajax({
url: ajaxSearchUrl,
type: "GET",
success: function(response){
var length = response.length;
var data = $(response).contents().find('#main').html();
var bread = $(response).contents().find('ul.breadcrumb');
var filter = $(response).contents().find('.filter').html();
sidebar.find('.init-search').removeClass('btn-loading').removeClass('disabled').attr('disabled', false);
sidebar.find('input[name="ajaxRun"]').val("");
$('#main').fadeOut(0, function(){
$('#main').html(data).show(0);
$('#search-items').hide(0);
$('#search-items').removeClass('loading');
$('#search-items').show(0).css('opacity', 0).css('margin-top', '50px').css('margin-bottom', '-50px').animate( { opacity: 1, marginTop:'0', marginBottom:'0'} , 300);
});
if(sidebarReload) {
$('.filter').html(filter);
}
$('ul.breadcrumb').html(bread);
I'm currently using a custom sort function on a dgrid (pasted below). It doesn't change sorting drastically, just sorts one particular column uniquely and sorts the others case-insensitive. I'd like to add a secondary sort by a column named "scheduled" to be added to the sort when any other column is sorted. I'm just not sure how to go about it. I've seen how to override the sort to sort by two columns, but not when a custom sort is in play. The secondary sort would always be there, not matter what other column is clicked.
For reference I'm running dojo 1.10 and dgrid 1.0. Data is coming from a RequestMemory DStore and I'd really rather this sort happen on the grid rather than back at the store level. Any help would be appreciated.
currGrid.on('dgrid-sort', function (event) {
event.preventDefault();
var sort = event.sort[0];
currGrid.set('sort', function (a, b) {
if (sort.property == "thisField") {
//special sort for thisField
if (a[sort.property] !== 'undefined' && typeof a[sort.property] == "string") {
var colorA = a[sort.property].split("|");
var aValue = colorA[0].toLowerCase();
}
if (b[sort.property] !== 'undefined' && typeof b[sort.property] == "string") {
var colorB = b[sort.property].split("|");
var bValue = colorB[0].toLowerCase();
}
if (String(aValue) == String(bValue)) {
var result = 0;
} else if (dojo.string.trim(aValue) == "") {
var result = true ? 1 : -1;
} else if (dojo.string.trim(bValue) == "") {
var result = true ? -1 : 1;
} else {
var result = aValue > bValue ? 1 : -1;
}
return result * (sort.descending ? -1 : 1);
} else {
//Sort for all other fields same as always (except toLowerCase)
if (a[sort.property] !== 'undefined' && typeof a[sort.property] == "string") {
var aValue = a[sort.property].toLowerCase();
} else {
var aValue = "";
}
if (b[sort.property] !== 'undefined' && typeof b[sort.property] == "string") {
var bValue = b[sort.property].toLowerCase();
} else {
var bValue = "";
}
var result = aValue > bValue ? 1 : -1;
return result * (sort.descending ? -1 : 1);
}
});
currGrid.updateSortArrow(event.sort, true);
});
currGrid.startup();
You could do something like below.
currGrid.on('dgrid-sort', function (event) {
event.preventDefault();
var sortSet = [];
sortSet.push(event.sort[0]);
sortSet.push({property: "scheduled"});
currGrid.set('sort', function (a, b) {
var aValue, bValue, result = 0;
for(var i = 0; i < sortSet.length; i++){
var sort = sortSet[i];
if (sort.property == "thisField") {
//special sort for thisField
if (a[sort.property] !== 'undefined' && typeof a[sort.property] == "string") {
var colorA = a[sort.property].split("|");
aValue = colorA[0].toLowerCase();
}
if (b[sort.property] !== 'undefined' && typeof b[sort.property] == "string") {
var colorB = b[sort.property].split("|");
bValue = colorB[0].toLowerCase();
}
if (String(aValue) == String(bValue)) {
result = 0;
} else if (dojo.string.trim(aValue) == "") {
result = true ? 1 : -1;
} else if (dojo.string.trim(bValue) == "") {
result = true ? -1 : 1;
} else {
result = aValue > bValue ? 1 : -1;
}
return result * (sort.descending ? -1 : 1);
} else {
//Sort for all other fields same as always (except toLowerCase)
if (a[sort.property] !== 'undefined' && typeof a[sort.property] == "string") {
aValue = a[sort.property].toLowerCase();
} else {
aValue = "";
}
if (b[sort.property] !== 'undefined' && typeof b[sort.property] == "string") {
bValue = b[sort.property].toLowerCase();
} else {
bValue = "";
}
//You need this check here
if(aValue != bValue){
result = aValue > bValue ? 1 : -1;
return result * (sort.descending ? -1 : 1);
}
}
}
return 0;
});
currGrid.updateSortArrow(event.sort, true);
});
currGrid.startup();
I have some concerns about your code, the variables result, aValue and bValue are all local within the if statement and yet they are being used outside the statement. It could result in wrong results if some other variables are defined with the same name in global space. So I have modified them.
So the second section you needed to check if aValue == bValue to return 0.
Here is one of queries I am using in my project:
var carQuery = from cars in context.Cars
.Where(c => c.CarID==3)
from stockTypes in context.StockTypes
.Where(st => cars.StockTypeId == st.StockTypeID).DefaultIfEmpty()
from carUnit in context.Car_Units
.Where(cu => cu.CarId == cars.CarID).DefaultIfEmpty()
from carAttributes in context.Car_Attributes
.Where(ca => ca.CarId == cars.CarID).DefaultIfEmpty()
from attribute in context.Attributes
.Where(attr => attr.AttributeId==carAttributes.AttributeId).DefaultIfEmpty()
select new
{
CarID = cars.CarID,
CarName = cars.CarName,
CarDescription = cars.CarDescription,
StockType = (stockTypes == null) ? null : new
{
StockTypeID = stockTypes.StockTypeID,
StockName = stockTypes.StockName
},
IsActive = cars.IsActive,
IsCab = cars.IsCab,
Unit = (carUnit == null) ? null : new
{
Id = carUnit.UnitId,
Name = carUnit.Unit.UnitName
},
Attributes = attribute
};
If the context.Attributes returns multiple rows, the whole resultset also returning multiple rows.
Is there any possibility to return a single car type with multiple attributes as a list of attributes to the car??
Please help.
Thanks,
Mahesh
You just need to move the attribute query inside the result set:
var carQuery = from cars in context.Cars
.Where(c => c.CarID==3)
from stockTypes in context.StockTypes
.Where(st => cars.StockTypeId == st.StockTypeID).DefaultIfEmpty()
from carUnit in context.Car_Units
.Where(cu => cu.CarId == cars.CarID).DefaultIfEmpty()
from carAttributes in context.Car_Attributes
.Where(ca => ca.CarId == cars.CarID).DefaultIfEmpty()
select new
{
CarID = cars.CarID,
CarName = cars.CarName,
CarDescription = cars.CarDescription,
StockType = (stockTypes == null) ? null : new
{
StockTypeID = stockTypes.StockTypeID,
StockName = stockTypes.StockName
},
IsActive = cars.IsActive,
IsCab = cars.IsCab,
Unit = (carUnit == null) ? null : new
{
Id = carUnit.UnitId,
Name = carUnit.Unit.UnitName
},
Attributes =
from attribute in context.Attributes
.Where(attr => attr.AttributeId==carAttributes.AttributeId).DefaultIfEmpty()
.GroupBy(at => at.AttributeId)
select attribute
};