How to speed up workflow with database .Net - c#

I have simple controller that return list of products.It is take about 5-7sec to return the data for the first time,and then 50-80ms ,but only if i run it immediately(10-30sec) after first one ,if i will run it after 2-3min it will be again 5-7s.
I dont store this list in cache,sow i cant understand why only first time it takes 5sec,and then 50ms.
Important:test that i have made is not on localhost,it is on the production server.On localhost it takes 50ms
How can i speed up?
Do i need to make any change in my code? Or IIS?
My code
public List<PackageModel> GetPromotionOrDefaultPackageList(string domain)
{
List<DBProduct> DBPackageList = new List<DBProduct>();
List<PackageModel> BllPackageList = new List<PackageModel>();
try
{
using (CglDomainEntities _entities = new CglDomainEntities())
{
DBPackageList = _entities.DBProducts
.Where(x =>
x.ProductGroup.Equals(domain + "-package")
&& x.IsPromotionProduct == true)
.ToList();
if (DBPackageList.Count == 0)
{
DBPackageList = _entities.DBProducts
.Where(x =>
x.ProductGroup.Equals(domain + "-package")
&& x.IsBasicProduct == true)
.ToList();
}
}
PackageModel bllPackage = new PackageModel();
foreach (DBProduct dbProduct in DBPackageList)
{
bllPackage = new PackageModel();
bllPackage.Id = dbProduct.Id;
bllPackage.ProductId = dbProduct.ProductId;
bllPackage.IsPromotionProduct = dbProduct.IsPromotionProduct.HasValue ? dbProduct.IsPromotionProduct.Value : false;
bllPackage.ProductName = dbProduct.ProductName;
bllPackage.ProductDescription = dbProduct.ProductDescription;
bllPackage.Price = dbProduct.Price;
bllPackage.Currency = dbProduct.Currency;
bllPackage.CampaignId = dbProduct.CampaignId;
bllPackage.PathToProductImage = dbProduct.PathToProductImage;
bllPackage.PathToProductPromotionImage = dbProduct.PathToProductPromotionImage;
bllPackage.PathToProductInfo = dbProduct.PathToProductInfo;
bllPackage.CssClass = dbProduct.CssClass;
BllPackageList.Add(bllPackage);
}
return BllPackageList;
}
catch (Exception ex)
{
Logger.Error(ex.Message);
return BllPackageList;
}
}

Related

I wanted to create different notification message. 1. Record successfully updated, 1. Updating Record Failed, 3. No changes were made in the record

My previous codes was:
protected async void UpdateHandler(GridCommandEventArgs args)
{
iLogBlazor.Domain.Models.Project project = (iLogBlazor.Domain.Models.Project)args.Item;
if (project != null)
{
try
{
project.Pic = null;//load the correct user based on the new PicUserId
await ProjectService.UpdateForOtherTables(project);
int i = Projects.FindIndex(x => x.Id == project.Id);
var updatedProject = await ProjectService.GetByProjectIdAsync(project.Id); //project;
int i2 = OriginalProjects.FindIndex(x => x.Id == updatedProject.Id);
var currentSelectedItems = new List<iLogBlazor.Domain.Models.Project>(SelectedItems);
int selectedItemIndex = currentSelectedItems.FindIndex(x => x.Id == updatedProject.Id);
if (i != -1)
{
// update the selected items collection
currentSelectedItems[selectedItemIndex] = updatedProject;
SelectedItems = currentSelectedItems;
// The actual Update operation for the view-model data. Add your actual data source operations here
OriginalProjects[i2] = updatedProject;
Projects[i] = updatedProject;
Grid?.Rebind();
}
NotificationService.Success("Record successfully updated.");
YAOptions = OriginalProjects.Select(p => p.Ya).Distinct().ToList();
}
catch (Exception e)
{
NotificationService.Error("Updating record failed.");
}
}
}
I am trying to modify with the codes below but I am always getting the success response even when I am not updating something.
{
iLogBlazor.Domain.Models.Project project = (iLogBlazor.Domain.Models.Project)args.Item;
if (project != null)
{
bool isSuccessful = false;
bool isFailed = false;
iLogBlazor.Domain.Models.Project originalProject = project;
try
{
project.Pic = null;//load the correct user based on the new PicUserId
await ProjectService.UpdateForOtherTables(project);
int i = Projects.FindIndex(x => x.Id == project.Id);
var updatedProject = await ProjectService.GetByProjectIdAsync(project.Id); //project;
int i2 = OriginalProjects.FindIndex(x => x.Id == updatedProject.Id);
var currentSelectedItems = new List<iLogBlazor.Domain.Models.Project>(SelectedItems);
int selectedItemIndex = currentSelectedItems.FindIndex(x => x.Id == updatedProject.Id);
if (i != -1)
{
// update the selected items collection
currentSelectedItems[selectedItemIndex] = updatedProject;
SelectedItems = currentSelectedItems;
// The actual Update operation for the view-model data. Add your actual data source operations here
OriginalProjects[i2] = updatedProject;
Projects[i] = updatedProject;
Grid?.Rebind();
// Check if any changes were made to the Project
bool changesMade = !Object.ReferenceEquals(originalProject, updatedProject);
if (changesMade)
{
isSuccessful = true;
}
}
}
catch (Exception e)
{
isFailed = true;
}
if (isSuccessful)
{
NotificationService.Success("Record successfully updated.");
}
else if (isFailed)
{
NotificationService.Error("Updating record failed.");
}
else
{
NotificationService.Error("No changes were made to the record.");
}
YAOptions = OriginalProjects.Select(p => p.Ya).Distinct().ToList();
}
}
both of the above code is always returning a response to success update. even when i am just triggering the row and not changing anything. I would really want to get three different notification message based on the condition i have provided above.

Performance issue when performing operations on entity objects

Im facing performance issue in below code in multiple foreach loops. First im getting a list of ReturnDetails and then based on detail id get the HandlingInfo object. Then based on value of action, update the ReturnsDetail Object again.
It take more than a minute for loading 3000 records of ReturnsDetail. While debugging locally, it runs for infinite amount of time.
Please let me know in anyway i can refactor this code .
Thanks for your help.
lstReturnsDetail = dcReturnsService.GetReturnDetailsInfo(header_id);
List<HandlingInfo> lstHandlingInfo = null;
foreach (ReturnsDetail oReturnsDetail in lstReturnsDetail)
{
using (DCReturns_Entities entities = new DCReturns_Entities())
{
lstHandlingInfo = entities.HandlingInfoes.Where(f => f.detail_id == oReturnsDetail.id).ToList();
if(lstHandlingInfo != null)
{
foreach (HandlingInfo oHandlingInfo in lstHandlingInfo)
{
if (oHandlingInfo.action == "DST")
{
oReturnsDetail.destroy += Convert.ToInt32(oHandlingInfo.qty);
}
else if (oHandlingInfo.action == "SHP")
{
oReturnsDetail.to_shop += Convert.ToInt32(oHandlingInfo.qty);
}
else if (oHandlingInfo.action == "RBX")
{
oReturnsDetail.in_stock += Convert.ToInt32(oHandlingInfo.qty);
}
}
}
}
oReturnsDetail.received_qty = oReturnsDetail.destroy + oReturnsDetail.to_shop + oReturnsDetail.in_stock;
}
dgReturnsDetail.DataSource = lstReturnsDetail.OrderByDescending(g => g.id).ToList();
Session[DCReturnsConstants.Returns_Detail_Entity] = lstReturnsDetail;
dgReturnsDetail.DataBind();
this is su-do code! but you should get the jist.
//modify this to return all of them into mem, and then filter on this...
//if it can not be done here then do below..
var lstReturnsDetail = dcReturnsService.GetReturnDetailsInfo(header_id);
//then create a list here which fetches all,
List<[type]> somelist
List<int> listId = lstReturnsDetail.select(x=>x.id).tolist();
using (var db = new DCReturns_Entities())
{
somelist = db.HandlingInfoes.Where(f => listId.Contains( f.detail_id)).ToList();
}
foreach (ReturnsDetail oReturnsDetail in lstReturnsDetail)
{
//performance issue is here
//using (DCReturns_Entities entities = new DCReturns_Entities())
//{
// lstHandlingInfo = entities.HandlingInfoes.Where(f => f.detail_id == oReturnsDetail.id).ToList();
//}
//insead fetach all before, into mem and filter from that list.
var lstHandlingInfo = somelist.Where(f => f.detail_id == oReturnsDetail.id).ToList();
//code ommited for reaablity
}
//code ommited for reaablity

ASP.NET Core Large Data Set Processing

I have an Asp.net core 2.1 application with a Postgresql database.
A large file (~100K lines) gets uploaded to the database and then each line is processed.
As each line is processed there are approximately 15 sub queries per line taking up about 10 seconds in total per line. I have tried optimizing the queries and loading certain datasets in memory to reduce database calls which has seen a slight improvement. I have also tried reducing the batch size but that has also had minimal reduction.
Are there any other ways I can speed this up? The queries are written in lambda.
The high level function:
public void CDR_Insert(List<InputTable> inputTable, IQueryable<Costing__Table> CostingTable, List<Patterns> PatternsTable, IQueryable<Country_Calling_Codes> CallingCodesTable, IQueryable<Country> CountryTable, string voicemail_number)
{
foreach (var row in inputTable)
{
//if (!string.IsNullOrEmpty(row.finalCalledPartyPattern))
//{
var rowexists = _context.CDR.Where(m => m.InputId == row.id).Count();
if (rowexists == 0)
{
if (ValidateIfOneNumberIsForCountry(row.callingPartyNumber, row.finalCalledPartyNumber, PatternsTable, CountryTable) == true)
{
var CallRingTime = TimeSpan.FromSeconds(Ring_Time(row.dateTimeOrigination, row.dateTimeConnect));
var Call_Direction = CallDirection(row.callingPartyNumber, row.finalCalledPartyNumber, row.finalCalledPartyPattern, voicemail_number);
var CallReason = "Destination Out Of Order";
if (row.dateTimeConnect != "0")
{
CallReason = Call_Reason(row.callingPartyNumber, row.originalCalledPartyNumber, row.finalCalledPartyNumber, voicemail_number);
}
var CallOutcome = Outcome(row.duration, row.dateTimeOrigination, row.dateTimeConnect, row.callingPartyNumber, row.originalCalledPartyNumber, row.finalCalledPartyNumber, voicemail_number);
var CallCategory = GetCategory(row.callingPartyNumber, row.finalCalledPartyNumber, PatternsTable, CallingCodesTable, CountryTable);
var CallCost = 0.00;
if (CallOutcome != "Not Connected" || CallOutcome != "No answer")
{
CallCost = Costing(row.callingPartyNumber, row.finalCalledPartyNumber, row.dateTimeConnect, row.dateTimeDisconnect, row.finalCalledPartyPattern, row.duration, Call_Direction, CostingTable, PatternsTable, voicemail_number, CallingCodesTable, CountryTable);
}
CDR cDR = new CDR()
{
Date_Time = UnixTimeStampToDateTimeConvertor2(row.dateTimeOrigination),
Call_Direction = Call_Direction,
Calling_Party = row.callingPartyNumber_uri,
Calling_Digits = row.callingPartyNumber,
Called_Party = row.finalCalledPartyNumber_uri,
Called_Digits = row.finalCalledPartyNumber,
Duration = TimeSpan.FromSeconds(Convert.ToDouble(row.duration)),
Cost = CallCost,
Reason = CallReason,
Outcome = CallOutcome,
Country_Code = "MUS",//_context.Country.Where(o => o.CountryCode == _CDRExtension.CountryCodeId(_CDRExtension.Call_Type_Id(row.callingPartyNumber))).Select(o => o.CountryCode).FirstOrDefault(),
Second_Ring_Time = CallRingTime,
Category = CallCategory,
CiscoInputId = row.id
};
_context.CDR.Add(cDR);
}
row.Processed = true;
row.DateAdded = DateTime.Now;
_context.Cisco_Input.Update(row);
// }
_context.SaveChanges();
}
}
}

How to incorporate criteria in Where method?

I want to ask about the WHERE condition in my search command. I'm calling web service (API) during searching and I want to put WHERE statement in my code but there's an error.
private async Task CallApi(string searchText = null)
{
long lastUpdatedTime = 0;
long.TryParse(AppSettings.ComplaintLastUpdatedTick, out lastUpdatedTime);
var currentTick = DateTime.UtcNow.Ticks;
var time = new TimeSpan(currentTick - lastUpdatedTime);
if (time.TotalSeconds > 1) {
int staffFk = Convert.ToInt32(StaffId);
var result = await mDataProvider.GetComplaintList(lastUpdatedTime, mCts.Token, staffFk);
if (result.IsSuccess)
{
// Save last updated time
AppSettings.ComplaintLastUpdatedTick = result.Data.Updated.ToString();
// Store data into database
if ((result.Data.Items != null) &&
(result.Data.Items.Count > 0))
{
var datas = new List<Complaint>(result.Data.Items);
**if (!string.IsNullOrEmpty(searchText))
{
datas = datas.Where(i => i.Description.Contains(searchText)
&& (i.SupervisorId.Equals(StaffId))
|| (i.ProblemTypeName.Contains(searchText)));
}
else
{
datas = datas.Where(i => i.SupervisorId.Equals(StaffId));
}**
Datas = new ObservableCollection<Complaint>(datas);
}
}
else if (result.HasError)
{
await mPageDialogService.DisplayAlertAsync("Error", result.ErrInfo.Message, "OK");
}
}
}
Both assignments of datas in the if ... else causes System.Collections.Generic.IEnumerable<ECS.Features.Complaints.Complaint>' to 'System.Collections.Generic.List<ECS.Features.Complaints.Complaint>'. An explicit conversions exists (are you missing a cast?) compilation errors:
I don't know how to use the WHERE condition there. Please help me. Thank you in advance for your concern.
datas is a List<Complaint> but you try to reassign it to IEnumerable<Complaint> with the Where statement. Add a ToList() after the Where to maintain type,
Or you could just declare datas as IEnumerable<Complaint>
IEnumerable<Complaint> datas = new List<Complaint>(result.Data.Items);
Issue is that datas is defined as being a List<Complaint>, and the return type of datas.Where(...) is an IEnumerable/IQueryable.
You could do:
datas = datas.Where(i => i.SupervisorId.Equals(StaffId)).ToList();
Complete code:
private async Task CallApi(string searchText = null)
{
long lastUpdatedTime = 0;
long.TryParse(AppSettings.ComplaintLastUpdatedTick, out lastUpdatedTime);
var currentTick = DateTime.UtcNow.Ticks;
var time = new TimeSpan(currentTick - lastUpdatedTime);
if (time.TotalSeconds > 1) {
int staffFk = Convert.ToInt32(StaffId);
var result = await mDataProvider.GetComplaintList(lastUpdatedTime, mCts.Token, staffFk);
if (result.IsSuccess)
{
// Save last updated time
AppSettings.ComplaintLastUpdatedTick = result.Data.Updated.ToString();
// Store data into database
if ((result.Data.Items != null) &&
(result.Data.Items.Count > 0))
{
var datas = new List<Complaint>(result.Data.Items);
if (!string.IsNullOrEmpty(searchText))
{
datas = datas.Where(i => i.Description.Contains(searchText)
&& (i.SupervisorId.Equals(StaffId))
|| (i.ProblemTypeName.Contains(searchText))).ToList();
}
else
{
datas = datas.Where(i => i.SupervisorId.Equals(StaffId)).ToList();
}
Datas = new ObservableCollection<Complaint>(datas);
}
}
else if (result.HasError)
{
await mPageDialogService.DisplayAlertAsync("Error", result.ErrInfo.Message, "OK");
}
}
}
You will then also have an error on the next line, Datas = new ObservableCollection becasue Datas is not defined, and if you meant datas, again, it will not be the List<> that you initially defined.

ApplicationData.LocalSettings not storing data?

I'm making an app where a use enters values for two times (starthour, startminute, endhour, endminute). I wrote a function that saves the values and then checks for value and puts the values inside the text boxes. However, it isn't working and I'm not sure why. I'm assuming its a mistake on my part, but I'm not exactly sure. Here's the code:
public async Task savedata()
{
while (true)
{
var localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
localSettings.Values["starthour1"] = starthour1.Text;
localSettings.Values["starthour2"] = starthour2.Text;
localSettings.Values["starthour3"] = starthour3.Text;
localSettings.Values["starthour4"] = starthour4.Text;
localSettings.Values["starthour5"] = starthour5.Text;
localSettings.Values["starthour6"] = starthour6.Text;
localSettings.Values["starthour7"] = starthour7.Text;
localSettings.Values["startminute1"] = startminute1.Text;
localSettings.Values["startminute2"] = startminute2.Text;
localSettings.Values["startminute3"] = startminute3.Text;
localSettings.Values["startminute4"] = startminute4.Text;
localSettings.Values["startminute5"] = startminute5.Text;
localSettings.Values["startminute6"] = startminute6.Text;
localSettings.Values["startminute7"] = startminute7.Text;
localSettings.Values["endhour1"] = endhour1.Text;
localSettings.Values["endhour2"] = endhour2.Text;
localSettings.Values["endhour3"] = endhour3.Text;
localSettings.Values["endhour4"] = endhour4.Text;
localSettings.Values["endhour5"] = endhour5.Text;
localSettings.Values["endhour6"] = endhour6.Text;
localSettings.Values["endhour7"] = endhour7.Text;
localSettings.Values["endminute1"] = endminute1.Text;
localSettings.Values["endminute2"] = endminute2.Text;
localSettings.Values["endminute3"] = endminute3.Text;
localSettings.Values["endminute4"] = endminute4.Text;
localSettings.Values["endminute5"] = endminute5.Text;
localSettings.Values["endminute6"] = endminute6.Text;
localSettings.Values["endminute7"] = endminute7.Text;
//get data
Object starthour1o = localSettings.Values["starthour1"];
if (starthour1o == null)
{
// No data
}
else
{
starthour1.Text = starthour1o.ToString();
}
Object starthour2o = localSettings.Values["starthour2"];
if (starthour2o == null)
{
// No data
}
else
{
starthour2.Text = starthour2o.ToString();
}
Object starthour3o = localSettings.Values["starthour3"];
if (starthour3o == null)
{
// No data
}
else
{
starthour3.Text = starthour3o.ToString();
}
Object starthour4o = localSettings.Values["starthour4"];
if (starthour4o == null)
{
// No data
}
else
{
starthour4.Text = starthour4o.ToString();
}
Object starthour5o = localSettings.Values["starthour5"];
if (starthour5o == null)
{
// No data
}
else
{
starthour5.Text = starthour5o.ToString();
}
Object starthour6o = localSettings.Values["starthour6"];
if (starthour6o == null)
{
// No data
}
else
{
starthour6.Text = starthour6o.ToString();
}
Object starthour7o = localSettings.Values["starthour7"];
if (starthour7o == null)
{
// No data
}
else
{
starthour7.Text = starthour7o.ToString();
}
await Task.Delay(10);
}
}
Two things you need to do, first you need to explicitly save your settings for them to be persisted by calling Save(). Somewhere in your code you need to do localSettings.Save() and it should work.
2nd, if you have saved settings the first thing your code does is overwrite them with the current values of the text boxes, the whole top section where it is localSettings.Values["Foo"] = Foo.Text needs to be moved to the bottom.
As a side comment, do you really need to be updating your code every 10 miliseconds? That is going to eat up a TON of resources in your program. A much more normal approach is load the values at start-up then save them at shutdown.

Categories

Resources