I'm having an issue with this data layer method
public async Task<(bool HasFailed, IList<string> ErrorMessages)> ApproveBillCancelRequest(IEnumerable<string[]> billsToApprove,
string userId, string operationId)
{
var callerInfo = Shared.CommonAcross.Helper.GetCaller();
InfoScope($"{LayerName} -> {callerInfo.MethodName} -> Started", operationId, userId);
var errorMessages = new List<string>();
using (var context = new FocusConnection())
{
var transaction = context.Database.BeginTransaction();
try
{
foreach (var billToApprove in billsToApprove)
{
var targetBillNumber = billToApprove[0];
var targetPayModeId = int.Parse(billToApprove[1]);
var entityBill = context.BILL_INFO_CANCEL_REQUESTS
.SingleOrDefault(where =>
where.BILL_NUMBER == targetBillNumber &&
where.PAY_MODE_ID == targetPayModeId);
if (entityBill == null)
{
errorMessages.Add($"Bill #{billToApprove[0]}, payment #{billToApprove[1]} was not found for cancel approval");
continue;
}
entityBill.BILL_INFO.LAST_MODIFIED_BY = userId;
entityBill.BILL_INFO.STAMP_DATE = DateTime.Now;
entityBill.BILL_INFO.INPUT_STATUS = 0;
var cancelledBill = new BILL_INFO_CANCELED
{
BILL_NUMBER = entityBill.BILL_NUMBER,
PAY_MODE_ID = entityBill.PAY_MODE_ID,
CASHIER_ID = entityBill.CASHIER_ID,
CANCELED_DATE = entityBill.CANCEL_REQUEST_DATE,
CANCEL_REQUESTED_BY = entityBill.CANCEL_REQUESTED_BY,
CANCEL_APPROVED_BY = userId,
REMARKS = entityBill.CANCELATION_REASON
};
// Add cancelled bill
context.BILL_INFO_CANCELEDS.Add(cancelledBill);
// Remove cancellation request
context.BILL_INFO_CANCEL_REQUESTS.Remove(context.BILL_INFO_CANCEL_REQUESTS.Single(where =>
where.BILL_NUMBER == cancelledBill.BILL_NUMBER && where.PAY_MODE_ID == cancelledBill.PAY_MODE_ID));
await context.SaveChangesAsync();
}
transaction.Commit();
}
catch (Exception exp)
{
transaction?.Rollback();
ErrorScope($"{LayerName} -> {callerInfo.MethodName} -> Exception [{exp.Message}]", exp, operationId, userId);
errorMessages.Add($"{LayerName} -> {callerInfo.MethodName} -> Exception [{exp.Message}]");
return (true, errorMessages);
}
}
return (errorMessages.Any(), errorMessages);
}
The issue is that in the ForEach loop, the first record is retrieved properly and processed. But the remaining records are never found (entityBill == null) but they are in the database. I believe it has something to do with the running transaction.
Can anyone help out?
This was a hard one to crack. It turns out that while String.Splitting() on the UI layer, there was an extra space being appended to the first index of the array within the List of arrays. So I fixed that by:
var targetBillNumber = billToApprove[0].Trim();
var targetPayModeId = int.Parse(billToApprove[1].Trim());
Related
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.
Hi I have Controller method as below
[HttpPost]
public JsonResult Post(string vehiclesString, string Entity, int EntityId, ApplicationUser CurrentUser)
{
//https://stackify.com/understanding-asp-net-performance-for-reading-incoming-data/
List<Vehicle> vehicles = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Vehicle>>(vehiclesString);
InputFieldController c = new InputFieldController();
var errors = new List<string>();
try
{
//let's get model for each of the input field
InputFieldController icController = new InputFieldController();
List<InputField> fields = icController.GetNamesValues("VehicleField", -1, "Vehicle", 0);
foreach (Vehicle vehicle in vehicles)
{
//convert array of strings into array of input fields
if (fields.Count != vehicle.ValueStrings.Count)
{
throw new Exception("Vehicle columns mismatch. Expected "
+ fields.Count + " fields, but received " + vehicle.ValueStrings.Count);
}
for (int i = 0; i < fields.Count; i++)
{
InputField field = fields[i];
string cell = vehicle.ValueStrings[i];
if ((cell != null || cell != String.Empty) && (field.Type == "radio" || field.Type == "dropdown"))
{
var f = field.InputDropdowns.Where(x => x.Name == cell).FirstOrDefault();
if (f != null)
{
field.InputValue.InputDropdownId = f.InputDropdownId;
}
else
field.InputValue.InputDropdownId = null;
}
else
{
field.InputValue.Value = cell;
}
vehicle.Values.Add(field);
}
vehicle.Blob = Newtonsoft.Json.JsonConvert.SerializeObject(vehicle.Values);
Vehicle v = new Vehicle();
if (vehicle.VehicleId == 0)
{
v = this.DomainLogicUnitOfWork.VehicleManager.Create(vehicle, Entity, EntityId);
}
}
JsonResult data = Json(new
{
success = true,
});
List<Vehicle> vehiclesList = this.DomainLogicUnitOfWork.VehicleManager.List(Entity, EntityId);
if (vehiclesList != null)
foreach (Vehicle v in vehiclesList)
{
if ((v != null) && (v.Blob != null))
v.Values = Newtonsoft.Json.JsonConvert.DeserializeObject<List<InputField>>(v.Blob);
}
//Task task = Task.Run(async () => await this.DomainLogicUnitOfWork.VehicleInfoManager.CreateOrUpdate(Entity, EntityId));
/*
* Here I have to call the this.DomainLogicUnitOfWork.VehicleInfoManager.CreateOrUpdate(string Entity, int EntityId) asynchronously
* but return the data without waiting for the CreateOrUpdate to complete
*/
System.Web.Hosting.HostingEnvironment.QueueBackgroundWorkItem(async cancellationToken =>
{
await this.DomainLogicUnitOfWork.VehicleInfoManager.CreateOrUpdate(vehiclesList, Entity, EntityId);
});
return data;
}
catch (Exception ex)
{
LogHandler.LogError(9000, "Error updating input fields", ex);
errors.Add("Error 9000:" + ex.Message);
return Json(new
{
error = ex.Message
});
}
}
And I have CreateOrUpdate method defined as below in VehicleInfoManager class
public async Task CreateOrUpdate(string Entity, int EntityId)
{
//do some stuff
var task = Task.Run(() => Test(Entity, EntityId));
//do other stuff
await task;
//some more stuff
}
And Test method is as follows
private void Test(string Entity, int EntityId)
{
List<VehicleInfo> addList; List<VehicleInfo> updateList;
try
{
this.GetAddAndUpdateList(Entity, EntityId, out addList, out updateList);
if ((addList != null) && (addList.Count > 0))
using (var cont = this.UnitOfWork.Context)
{
foreach (var a in addList)
{
cont.VehicleInfos.Add(a);
}
cont.SaveChanges();
}
if ((updateList != null) && (updateList.Count > 0))
using (var cont = this.UnitOfWork.Context)
{
foreach (var a in updateList)
{
var aa = cont.VehicleInfos?.Where(x => x.VehicleInfoId == a.VehicleInfoId)?.FirstOrDefault();
aa.Address_City = a.Address_City;
aa.Address_Country = a.Address_Country;
aa.Address_StateCode = a.Address_StateCode;
aa.Address_Street1 = a.Address_Street1;
aa.Address_Street2 = a.Address_Street2;
aa.Address_Zip = a.Address_Zip;
aa.ChassisYear = a.ChassisYear;
aa.EngineFamilyName = a.EngineFamilyName;
aa.Entity = a.Entity;
aa.EntityId = a.EntityId;
aa.InputFieldEntity = a.InputFieldEntity;
aa.InputFieldEntityId = a.InputFieldEntityId;
aa.InputFieldGroup = a.InputFieldGroup;
aa.LicensePlate = a.LicensePlate;
aa.Manufacturer = a.Manufacturer;
aa.ModelYear = a.ModelYear;
aa.PurchasedDate = a.PurchasedDate;
aa.RegHoldClearBy = a.RegHoldClearBy;
aa.RegHoldClearDate = a.RegHoldClearDate;
aa.RegHoldComment = a.RegHoldComment;
aa.RegHoldSet = a.RegHoldSet;
aa.RegHoldSetBy = a.RegHoldSetBy;
aa.RegHoldSetDate = a.RegHoldSetDate;
aa.TrailerPlate = a.TrailerPlate;
aa.UpdatedBy = a.UpdatedBy;
aa.UpdatedDate = a.UpdatedDate;
aa.VehicleId = a.VehicleId;
aa.VehicleOperator = a.VehicleOperator;
aa.VehicleOwner = a.VehicleOwner;
aa.VIN = a.VIN;
}
cont.SaveChanges();
}
}
catch (Exception ex)
{
ARB.Logging.LogHandler.LogError(9001, "CreateOrUpdate(string Entity, int EntityId) in class VehicleInfoManager", ex);
throw ex;
}
}
What I want is, I want two things here
the Post method to call or start the CreateOrUpdate method as background call but instead of waiting until the CreateOrUpdate method finishes, it should return the result data to UI and continue the big task CreateOrUpdate in the background.
Is there anyway to start the background method CreateOrUpdate after sometime like (10 mins etc) post method returns to UI, if it can't be done, its OK we don't have to worry but just asking if there is anyway to trigger this from within the same application
When I implemented it in the above way, even after using System.Web.Hosting.HostingEnvironment.QueueBackgroundWorkItem I am still getting the null http context at the following location
user = System.Web.HttpContext.Current.User.Identity.Name; url = System.Web.HttpContext.Current.Request.Url.ToString();
System.Web.HttpContext.Current is coming out as null.
and the application is breaking,
I chaned my async call to the following to use HostingEnvironment.QueueBackgroundWorkItem, still the same htt current context is coming out as null, any help please
System.Web.Hosting.HostingEnvironment.QueueBackgroundWorkItem(async cancellationToken =>
{
await this.DomainLogicUnitOfWork.VehicleInfoManager.CreateOrUpdate(Entity, EntityId);
});
Thank you
System.Web.HttpContext.Current is maintained by the ASP.NET's SynchronizationContext.
When you start a new Task, the code will be executing on another thread pool thread without a SynchronizationContext and the value of System.Web.HttpContext.Current is not safe to use, whatever its value.
When the execution of the action method (Post) ends, the request will end and the HttpContext instance will be invalid, even if you mange to get a reference to it.
Also, there is no guarantee that that code you posted to the thread pool will run to complete, since it's out of ASP.NET control and ASP.NET won't be aware of it if IIS decides, for some reason, to recycle the application pool or the web application.
If you to post background work, use HostingEnvironment.QueueBackgroundWorkItem. Beware if its constraints.
I run this query through both C# code and in Data Explorer
SELECT c._ts, c.id, c.sensors, c.meta, c.partition
FROM c
WHERE c.partition IN ("1320","1321","1321")
AND c.meta.created.ts >= 1597096800
AND c.meta.created.ts <= 1648418399
AND IS_DEFINED(c.sensors)
ORDER BY c.meta.created.ts DESC
Request Charge in Data Explorer
19.7 RUs
Request Charge from code
1334.5 RUs
This part is only run once. There is no loop
public async Task<CosmosDbResult> ListWithStreamAsync(string continuationToken = null)
{
try
{
var result = new CosmosDbResult();
double requestCharge = 0;
var sqlQueryText = "SELECT c._ts, c.id, c.sensors, c.meta, c.partition FROM c WHERE c.partition IN (\"1320\",\"1321\",\"1321\") AND c.meta.created.ts >= 1597096800 AND c.meta.created.ts <= 1648418399 AND IS_DEFINED(c.sensors) ORDER BY c.meta.created.ts DESC";
var queryDefinition = new QueryDefinition(sqlQueryText);
using (var queryResultSetIterator =
this.container.GetItemQueryIterator<Dictionary<string, object>>(queryDefinition, Base64Decode(continuationToken)))
{
if (queryResultSetIterator.HasMoreResults)
{
var currentResultSet = await queryResultSetIterator.ReadNextAsync();
result.RequestCharge = currentResultSet.RequestCharge;
result.Data = currentResultSet;
}
log.AddNotice($"Listed items for partition {ids}. Operation consumed {requestCharge} RUs.", new object[] { ids, requestCharge });
return result;
}
}
catch (Exception ex)
{
throw ex;
}
}
How can it be such high difference with the same query? This just started to happen a couple of days ago like Microsoft have updated Cosmos DB as my backend haven't changed.
Kind regards Daniel
Adding MaxItemCount = 100 to GetItemQueryIterator resulted in much better performance.
using (var queryResultSetIterator =
this.container.GetItemQueryIterator<Dictionary<string, object>>(queryDefinition, Base64Decode(continuationToken), requestOptions: new QueryRequestOptions()
{
MaxItemCount = 100
}))
{
if (queryResultSetIterator.HasMoreResults)
{
var currentResultSet = await queryResultSetIterator.ReadNextAsync();
result.RequestCharge = currentResultSet.RequestCharge;
if (oData.GroupBy == null && currentResultSet.ContinuationToken != null)
{
result.ContinuationToken = Base64Encode(currentResultSet.ContinuationToken);
}
result.Data = currentResultSet;
result.Query = sqlQueryText;
}
log.AddNotice($"Listed items for partition {ids}. Operation consumed {requestCharge} RUs.", new object[] { ids, requestCharge });
return result;
}
I have a calculation that does I/O I want to send to another thread so on the web site the user can goto the next page without waiting for the calculation to finish. From what I understand are I need to do is call the method like this
var backgroundTask = Task.Run(() => CalculateSet(uow, profile, userId, specialtyCode ));
But when I do this is seems to call one line in the method and goes away.. non of the work is done.
Am I missing something ?
[Fact]
public void Calculation_Xls()
{
string currentDirectory = Directory.GetCurrentDirectory();
string filesDirectory = currentDirectory + "\\Files";
System.Text.Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
var builder = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json");
Configuration = builder.Build();
var optionsBuilder = new DbContextOptionsBuilder<RetContext>();
optionsBuilder.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
int i = 0; //outer loop
UnitOfWork uow = new UnitOfWork(new RetContext(optionsBuilder.Options));
using (var stream = System.IO.File.Open(filesDirectory + "\\t2UserProfileDataTwoUserPerSpecialty.xlsx",
FileMode.Open, FileAccess.Read))
{
using (var reader = ExcelReaderFactory.CreateReader(stream))
{
do
{
while (reader.Read())
{
if (i != 0)
{
var userId = reader.GetString(0);
var specialtyCode = reader.GetString(1);
var userProfileElement1_WorkExp = reader.GetValue(2);
var userProfileElement2_VolExp = reader.GetValue(3);
var userProfileElement3_ResExp = reader.GetValue(4);
var userProfileElement4_Pubs = reader.GetValue(5);
var userProfileElement5_AOA = reader.GetValue(6);
var userProfileElement6_Nspecialties = reader.GetValue(7);
var userProfileElement7_PercentApps = reader.GetValue(8);
//Create profile
UserProfileData profile = new UserProfileData();
profile.UserProfileElement1_WorkExp = Convert.ToInt32(userProfileElement1_WorkExp);
profile.UserProfileElement2_VolExp = Convert.ToInt32(userProfileElement2_VolExp);
profile.UserProfileElement3_ResExp = Convert.ToInt32(userProfileElement3_ResExp);
profile.UserProfileElement4_Pubs = Convert.ToInt32(userProfileElement4_Pubs);
profile.UserProfileElement5_Aoa = Convert.ToBoolean(userProfileElement5_AOA);
profile.UserProfileElement6_Nspecialties = Convert.ToInt32(userProfileElement6_Nspecialties);
profile.UserProfileElement7_PercentApps = Convert.ToInt32(userProfileElement7_PercentApps);
//Calculate for set of programs. Selects one row at a time from XLS. BulkInsert into DB
//THIS ONLY RUNS ONE LINE OF THE METHOD
var backgroundTask = Task.Run(() => CalculateSet(uow, profile, userId, specialtyCode ));
//THIS WORKS
//CalculateSet(uow, profile, userId, specialtyCode);
}
i++;
Debug.WriteLine("Bulkcreate complete " + i);
//only process xxx rows
if (i > 1)
{
break;
}
}
} while (reader.NextResult());
}
}
Debug.WriteLine("Should get here quickly and not wait until task is done");
}
private void CalculateSet(UnitOfWork uow, UserProfileData profile, string userId, string specialtyCode)
{
//I CAN HIT THIS BREAKPOINT!
//get specialtyId from code
var specialtyId = uow.RefMedicalSpecialtyRepository
.Find(x => x.Code == specialtyCode).FirstOrDefault().Id;
//NEVER GET TO THIS BREAKPOINT
//loop through all programs for speciality
var programsForSpecialty = uow.RefProgramDetailDataRepository
.Find(x => x.RefMedicalSpecialtyId == specialtyId);
//List for bulk insert
// List<UserProgram> userPrograms = new List<UserProgram>();
//Write a row for each program
foreach (RefProgramDetailData rpdd in programsForSpecialty.ToList())
{
//Get program info
var programProfile = LoadData.Load_RefProgramProfileData(rpdd.Code);
//Calculate results
var userProgram = _calculator.CalculateAll(programProfile, profile, specialtyId, userId);
//If the Program can not be found in program detail then skip insert
if (userProgram == null)
{
Debug.WriteLine("Program NULL");
}
else
{
//Write results to UserProgram
uow.UserProgramRepository.Create(userProgram);
//userPrograms.Add(userProgram);
Debug.WriteLine("Program " + programProfile.ProgramCode);
}
}
//bulk insert
// uow.UserProgramRepository.BulkCreate(userPrograms);
}
}
EDIT 1: I put this in my controller. But it is waiting for the Task to finish before it redirects. Why isn't it redirecting immediately ?
await Task.Run(() => _calculator.CalculateAllSet(_unitOfWork, userProfileData, msId, null));
return RedirectToAction("Index", "Home");
Can you try like that.
[Fact]
public async Task Calculation_Xls()
{
string currentDirectory = Directory.GetCurrentDirectory();
string filesDirectory = currentDirectory + "\\Files";
System.Text.Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
var builder = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json");
Configuration = builder.Build();
var optionsBuilder = new DbContextOptionsBuilder<RetContext>();
optionsBuilder.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
int i = 0; //outer loop
UnitOfWork uow = new UnitOfWork(new RetContext(optionsBuilder.Options));
using (var stream = System.IO.File.Open(filesDirectory + "\\t2UserProfileDataTwoUserPerSpecialty.xlsx",
FileMode.Open, FileAccess.Read))
{
using (var reader = ExcelReaderFactory.CreateReader(stream))
{
do
{
while (reader.Read())
{
if (i != 0)
{
var userId = reader.GetString(0);
var specialtyCode = reader.GetString(1);
var userProfileElement1_WorkExp = reader.GetValue(2);
var userProfileElement2_VolExp = reader.GetValue(3);
var userProfileElement3_ResExp = reader.GetValue(4);
var userProfileElement4_Pubs = reader.GetValue(5);
var userProfileElement5_AOA = reader.GetValue(6);
var userProfileElement6_Nspecialties = reader.GetValue(7);
var userProfileElement7_PercentApps = reader.GetValue(8);
//Create profile
UserProfileData profile = new UserProfileData();
profile.UserProfileElement1_WorkExp = Convert.ToInt32(userProfileElement1_WorkExp);
profile.UserProfileElement2_VolExp = Convert.ToInt32(userProfileElement2_VolExp);
profile.UserProfileElement3_ResExp = Convert.ToInt32(userProfileElement3_ResExp);
profile.UserProfileElement4_Pubs = Convert.ToInt32(userProfileElement4_Pubs);
profile.UserProfileElement5_Aoa = Convert.ToBoolean(userProfileElement5_AOA);
profile.UserProfileElement6_Nspecialties = Convert.ToInt32(userProfileElement6_Nspecialties);
profile.UserProfileElement7_PercentApps = Convert.ToInt32(userProfileElement7_PercentApps);
//Calculate for set of programs. Selects one row at a time from XLS. BulkInsert into DB
//THIS ONLY RUNS ONE LINE OF THE METHOD
var backgroundTask = await Task.Run(() => CalculateSet(uow, profile, userId, specialtyCode ));
//THIS WORKS
//CalculateSet(uow, profile, userId, specialtyCode);
}
i++;
Debug.WriteLine("Bulkcreate complete " + i);
//only process xxx rows
if (i > 1)
{
break;
}
}
} while (reader.NextResult());
}
}
Debug.WriteLine("Should get here quickly and not wait until task is done");
}
private void CalculateSet(UnitOfWork uow, UserProfileData profile, string userId, string specialtyCode)
{
//I CAN HIT THIS BREAKPOINT!
//get specialtyId from code
var specialtyId = uow.RefMedicalSpecialtyRepository
.Find(x => x.Code == specialtyCode).FirstOrDefault().Id;
//NEVER GET TO THIS BREAKPOINT
//loop through all programs for speciality
var programsForSpecialty = uow.RefProgramDetailDataRepository
.Find(x => x.RefMedicalSpecialtyId == specialtyId);
//List for bulk insert
// List<UserProgram> userPrograms = new List<UserProgram>();
//Write a row for each program
foreach (RefProgramDetailData rpdd in programsForSpecialty.ToList())
{
//Get program info
var programProfile = LoadData.Load_RefProgramProfileData(rpdd.Code);
//Calculate results
var userProgram = _calculator.CalculateAll(programProfile, profile, specialtyId, userId);
//If the Program can not be found in program detail then skip insert
if (userProgram == null)
{
Debug.WriteLine("Program NULL");
}
else
{
//Write results to UserProgram
uow.UserProgramRepository.Create(userProgram);
//userPrograms.Add(userProgram);
Debug.WriteLine("Program " + programProfile.ProgramCode);
}
}
//bulk insert
// uow.UserProgramRepository.BulkCreate(userPrograms);
}
}
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.