Count doesn't consider the newly inserted record - c#

After inserting the first record, the count shows 0 even after the insert. I can see the the record inserted as soon as SaveContext()
is executed. So looks like userChangeRequestApprovalRepository isnt refreshed with the newly inserted data.
Is it appropriate to do count + 1 like the statement below instead
userChangeRequestApprovalRepository.Where(x => x.UserChangeRequestId == userChangeRequest.Id).Count() + 1;
Code
InsertUserChangeRequestApproval(userChangeRequest);
SaveContext();
var numberOfAprovals = userChangeRequestApprovalRepository.Where(x => x.UserChangeRequestId == userChangeRequest.Id).Count();
insert method
private void InsertUserChangeRequestApproval(UserChangeRequest userChangeRequest)
{
UserChangeRequestApproval userChangeRequestApproval = new UserChangeRequestApproval()
{
UserChangeRequestId = userChangeRequest.Id,
ApprovedByAuthUserId = userChangeRequest.ChangedByAuthUserId,
ApprovedDateTime = DateTime.Now,
IsActive = true
};
UserChangeRequestApprovalRepository.Insert(userChangeRequestApproval);
}
public virtual void Insert(TEntity entity)
{
_dbSet.Add(entity);
}
SaveContext method
public int SaveContext()
{
return _context.SaveChanges();
}
The code for the whole method
public IdentityResult ApproveUserChangeRequest(UserChangeRequest userChangeRequest, int approvedByAuthUserId, string authApplicationName)
{
var userChangeRequestRepository = UserChangeRequestRepository.GetAllAsList();
var userChangeRequestApprovalRepository = UserChangeRequestApprovalRepository.GetAllAsList();
var appSettingRepository = AppSettingRepository.GetAllAsList();
var clientCompanyContactRepository = ClientCompanyContactRepository.GetAllAsList();
var applicationUserRepo = ApplicationUserRepo.GetAllAsList();
// int approvedByAuthUserID = GetApprovedByUserId(authApplicationName, approvedByAuthUserName);
// Check if UserChangeRequest is still Pending
bool isUserChangeRequestPending = userChangeRequestRepository.Any(x => x.Id == userChangeRequest.Id && x.ChangeStatus == "Pending");
if (isUserChangeRequestPending && approvedByAuthUserId > 0)
{
// Inserting record in the UserChangeRequestApproval table
InsertUserChangeRequestApproval(userChangeRequest);
SaveContext();
using (var userTransaction = Context.Database.BeginTransaction())
{
using (var securityTransaction = _securityContext.Database.BeginTransaction())
{
try
{
//Get the Number of approval required for Internal and External Users
int? internalApprovalsRequired = GetApprovals("InternalUserChangeRequestApprovalsRequired", appSettingRepository);
int? externalApprovalsRequired = GetApprovals("ExternalUserChangeRequestApprovalsRequired", appSettingRepository);
//Get the name of the application the auth user belongs to
var authUserApplicationName = GetApplicationName(userChangeRequest.AuthUserId);
//Get the Number of approvals for the request
var numberOfAprovals = userChangeRequestApprovalRepository.Where(x => x.UserChangeRequestId == userChangeRequest.Id).Count();
//If the number of approvals is equal or greater than the Approvals required then Update AppUser or Contact details
if ((authUserApplicationName == "ArgentexTrader" && numberOfAprovals >= internalApprovalsRequired) || (authUserApplicationName == "ArgentexClient" && numberOfAprovals >= externalApprovalsRequired))
{
//Updating the clientcontact table
UpdateClientContact(userChangeRequest, clientCompanyContactRepository);
//Updating the auth user table
UpdateAuthUser(userChangeRequest);
//Updating the IdentityDB user table
UpdateIdentityDBUser(userChangeRequest, applicationUserRepo);
//Updating the UserChangeRequest table
userChangeRequest.ChangeStatus = "Approved";
UserChangeRequestRepository.Update(userChangeRequest);
SaveContext();
userTransaction.Commit();
securityTransaction.Commit();
return IdentityResult.Success;
}
}
catch (Exception ex)
{
userTransaction.Rollback();
securityTransaction.Rollback();
_logger.Error(ex);
return IdentityResult.Failed(new IdentityError { Description = ex.Message });
}
}
}
}
return null;
}

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.

How to handle New transaction is not allowed because there are other threads running in the session for multiple calls or to save as list of Entities

Hi I am using Entity Framework Code First, I have a collection of Entities that need to be saved, but I have my EF Repository created as below
public T Create(T item)
{
try
{
if (ufb != null && ufb.CurrentUser != null)
{
SetValue("CreatedByUserId", item, ufb.CurrentUser.Id);
SetValue("UpdatedByUserId", item, ufb.CurrentUser.Id);
}
SetValue("DateCreated", item, DateTime.Now);
SetValue("DateUpdated", item, DateTime.Now);
var newEntry = this.DbSet.Add(item);
this.Context.Database.Log = message => LogHandler.LogInfo(1111, message);
try
{
this.Context.SaveChanges();
}
catch (Exception ex)
{
LogHandler.LogInfo(2501, ex.Message);
}
BuildMetaData(item, true, true);
return newEntry;
}
catch (DbEntityValidationException dbEx)
{
// http://forums.asp.net/t/2014382.aspx?Validation+failed+for+one+or+more+entities+See+EntityValidationErrors+property+for+more+details+
string msg = string.Empty;
foreach (var validationErrors in dbEx.EntityValidationErrors)
{
foreach (var validationError in validationErrors.ValidationErrors)
{
msg += validationError.PropertyName;
msg += "---";
msg += validationError.ErrorMessage;
msg += "||";
}
}
throw new Exception("7777 CREATE EntityValidationErrors: " + msg);
}
}
My calling method is as below:
public List<VehicleInfo> Create(List<VehicleInfo> vehicleInfos, string Entity, int EntityId)
{
bool vehicleExists = false; List<VehicleInfo> newVehicleInfos = null;
if ((vehicleInfos != null) && (vehicleInfos.Count > 0))
{
newVehicleInfos = new List<VehicleInfo>();
foreach (VehicleInfo vehicleInfo in vehicleInfos)
{
vehicleExists = false;
if (vehicleInfo != null)
{
vehicleExists = this.VehicleExists(vehicleInfo.VehicleId, Entity, EntityId);
vehicleInfo.Entity = Entity;
vehicleInfo.EntityId = EntityId;
VehicleInfo v = this.UnitOfWork.VehicleInfoRepository.Create(vehicleInfo);
newVehicleInfos.Add(v);
}
}
}
return newVehicleInfos;
}
Hence when I am calling repositories create method for multiple times, its throwing me the above error, any help or suggestion would be very helpful, please thank you.
void BuildMetaDataNoThread(object item, bool active, bool isNew = false)
{
if (item.GetType() != typeof(JsonObject))
{
var dm = new DataAccessUnitOfWork(Constants.DefaultConnection);
var qtype = item.GetType();
if (qtype.BaseType.BaseType != null)
{
if ((isNew && qtype.BaseType.Name == typeof(ModelBase).Name) | qtype.BaseType.BaseType.Name == typeof(ModelBase).Name)
{
Thread.Sleep(500);
//collect data
var element = (ModelBase)item;
element.BuildMetaData(DataRequestType.CurrentItem);
var records = ModelBase.MetaData;
ModelBase.MetaData = new List<ModelRecord> { };
if (records == null) return;
foreach (ModelRecord r in records)
{
if (r!=null)
{
var jsr = new JavaScriptSerializer();
//object meta = r;
object rdata = r.Data;
var type = rdata.GetType();
var token = type.BaseType.Name;
List<string> include = r.Include;
// Cycle-through clieanup of models to be encoded into Json Data.
// this helper eliminates infinate relations by including records specified
// by a list of strings
if (include.Where(x => x.Contains("CreatedByUser")).Count() == 0)
include.Add("CreatedByUser");
if (include.Where(x => x.Contains("UpdatedByUser")).Count() == 0)
include.Add("UpdatedByUser");
var data = ClassCloner.CollectData(rdata, include);
List<string> tags = ClassCloner.CollectTags(data);
string _tags = "";
tags.ForEach((xtm) =>
{
_tags += xtm + ',';
});
var json = jsr.Serialize(data);
int id = 0;
//get identity
foreach (var prop in type.GetProperties())
{
if (id == 0)
{
foreach (var cp in prop.CustomAttributes)
{
if (cp.AttributeType.Name == "KeyAttribute")
{
var _id = ((Dictionary<string, object>)data)[prop.Name];
id = (int)_id;
break;
}
}
}
else { break; }
}
var query = dm.JsonObjectRepository.GetAll();
var key = "_" + token;
var _data = (Dictionary<string, object>)data;
var ExistingMetaData = (from x in query where x.SourceKey == key && x.SourceId == id select x).FirstOrDefault();
if (ExistingMetaData != null)
{
if (_data.ContainsKey("DateUpdated")) ExistingMetaData.Date = (DateTime)_data["DateUpdated"];
ExistingMetaData.SourceData = data;
ExistingMetaData.Encode();
ExistingMetaData.Active = active;
ExistingMetaData.SearchTags = _tags;
dm.JsonObjectRepository.Update(ExistingMetaData);
}
else
{
var newData = new JsonObject
{
Active = true,
Date = (DateTime)_data["DateUpdated"],
SourceData = data,
SourceId = id,
SourceKey = key,
SearchTags = _tags,
TargetKey = "GlobalSearchMetaData"
};
newData.Encode();
dm.JsonObjectRepository.Create(newData);
}
}
}
}
}
}
}
void BuildMetaData(object dataRecord, bool active, bool isNew)
{
new Thread((item) => { BuildMetaDataNoThread(item, active, isNew); }).Start(dataRecord);
}

Unable to find entity while under a transaction

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

Entity saves ok but will not update record no matter what I do

Context is not saving to the database no matter what i do it will insert a new record fine but not save. This is using sql server and the user had permissions ot update data have already checked this
private void btnOk_Click(object sender, EventArgs e)
{
SourceContext SourceDal = new SourceContext();
Appointment _appointment = new Appointment();
int errorCount = 0;
Patient _patient = new Patient();
_patient = SourceDal.getPatientByPatientId(txtPatientId.Text);
_patient.SSN = txtSSN.Text;
_patient.FirstName = txtPatientFirstName.Text;
_patient.LastName = txtPatientLastName.Text;
_patient.Middle = txtPatientMiddle.Text;
_patient.AddressOne = txtPatientAddressOne.Text;
_patient.City = txtPatientCity.Text;
_patient.State = txtPatientState.Text;
_patient.ZipCode = txtPatientZip.Text;
_patient.HomePhone = txtPatientHomePhone.Text;
_patient.WorkPhone = txtPatientWorkPhone.Text;
_patient.CellPhone = txtPatientCellPhone.Text;
if (rBtnHomePhone.Checked == true)
_patient.ApptPhone = txtPatientHomePhone.Text;
if (rBtnHomePhone.Checked == true)
_patient.ApptPhone = txtPatientHomePhone.Text;
if (rBtnWorkPhone.Checked == true)
_patient.ApptPhone = txtPatientWorkPhone.Text;
_patient.BirthDate = dtBirthDate.DateTime;
_patient.emailAddress = txtPatientEmail.Text;
_patient.Race = (int)dpRace.SelectedValue;
_patient.Ethnicity = (int)dpEthnicity.SelectedValue;
_patient.Language = (int)dpLanguages.SelectedValue;
_patient.AlertNote = txtPatientNotes.Text;
if (dpGender.Text == "")
{
dpGender.Focus();
errorCount = 1;
lblGenderRequired.Text = "* Gender is required.";
}
else
{
errorCount = 0;
lblGenderRequired.Visible = false;
}
_patient.Gender = dpGender.Text.Substring(0, 1);
_patient.PatientID = txtPatientId.Text;
txtPatientFirstName.Text = _patient.FirstName;
txtPatientLastName.Text = _patient.LastName;
// IF ITS SAVE NEW GO AHEAD ADD IT TO THE CONTEXT.
SourceDal.AddToPatient(_patient);
}
Add to paitent has the following
public void AddToPatient(Patient newPatient)
{
using (var myContext = new SMBASchedulerEntities(this.Connectionstring))
{
myContext.Patients.Add(newPatient);
if (newPatient.ID == 0)
{
myContext.Entry(newPatient).State = EntityState.Added;
}
else
{
myContext.Entry(newPatient).State = EntityState.Modified;
}
try
{
myContext.SaveChanges();
}
catch (DbEntityValidationException ex)
{
foreach (var entityValidationErrors in ex.EntityValidationErrors)
{
foreach (var validationError in entityValidationErrors.ValidationErrors)
{
Console.Write("Property: " + validationError.PropertyName + " Error: " + validationError.ErrorMessage);
}
}
}
}
}
It adds in the record fine but it just wont save the current record no matter what i do even though all the details are correct. But when i reload the form and the application the update is not there the email address is not saved no are any the other updates.
I suspect I'm not familiar with that entity framework, as I'm unfamiliar with the some of that syntax, but you should be able to use something like this:
public void AddToPatient(Patient newPatient)
{
SMBASchedulerEntities dbContext = new SMBASchedulerEntities();
if (newPatient.ID.ToString() != "0")
{//Update the record
Patient updatePatient = dbContext.Patients.Single(p => p.ID == newPatient.ID);
updatePatient.FirstName = newPatient.FirstName;
updatePatient.LastName = newPatient.LastName;
...
...
dbContext.SubmitChanges();
}
else
{//Insert a new record
Patient insertPatient = new Patient();
insertPatient.FirstName = newPatient.FirstName;
insertPatient.LastName = newPatient.LastName;
...
...
dbContext.Patients.InsertOnSubmit(insertPatient);
dbContext.SubmitChanges();
}
}
To put this another way, check to see if you need to insert or update a new patient first, before inserting it every time.

How to speed up sql creating process

in my app, i create rows to sql table.
int findNewId = Entities.myTable.Where(a => a.Name == txtName.Text).Select(b => b.Id).FirstOrDefault();
for (int i = 0; i < incomingDtbl.Rows.Count; i++)
{
addNew.Id = findNewId;
addNew.Date = Convert.ToDateTime(incomingDtbl.Rows[i].ItemArray[2]);
addNew.Hour = Convert.ToInt32(incomingDtbl.Rows[i].ItemArray[3]);
...
addNew.CreationDate = System.DateTime.Now;
Entities.myTable.Add(addNew);
Entities.SaveChanges();
}
but my incomingDtbl has like 130000 rows, so it takes soooo long.
is there any way to speed this process up?
i cant directly bulk copy the incomingDtbl because it doesnt have newId.
I have faced similar problem as well (Mine were 170,000 rows). Here's my solution:
public bool InsertData(List<MachineInfo> MachineInfo, string flag,int userID)
{
if (MachineInfo != null && flag != string.Empty)
{
List<T> attList = new List<T>();
foreach (var item in MachineInfo)
{
T att = new T()
{
CreatedDate = DateTime.Now,
DateTime = item.DateTimeRecord,
EnrollNumber = item.EnrollNumber.ToString(),
IPFlag = flag,
SyncBy = userID
};
attList.Add(att);
}
try
{
Entities context = null;
try
{
context = new Entities();
context.Configuration.AutoDetectChangesEnabled = false;
int count = 0;
foreach (var entity in attList)
{
++count;
context = AddToContext(context, entity, count, 100, true);
}
context.SaveChanges();
}
finally
{
if (context != null)
context.Dispose();
}
return true;
}
catch (Exception ex)
{
return false;
}
}
return false;
}
private Entities AddToContext(Entities context, T entity, int count, int commitCount, bool recreateContext)
{
context.Set<T>().Add(entity);
if (count % commitCount == 0)
{
context.SaveChanges();
if (recreateContext)
{
context.Dispose();
context = new Entities();
context.Configuration.AutoDetectChangesEnabled = false;
}
}
return context;
}
It performs really fast because it splits the records and also help you validate.
All the best!!!

Categories

Resources