How to speed up sql creating process - c#

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!!!

Related

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

BLToolKIT to Entity Framework help needed

I am creating a method for checking the product key. everything working fine in bltoolkit the code is
private void CheckKey()
{
try
{
using (DbManager db = new DbManager())
{
DataTable dt = db
.SetCommand("SELECT TOP 1 * FROM TblReg WHERE ProductKey=#ProductKey",
db.Parameter("#ProductKey", CommanClass.strRegkey))
.ExecuteDataTable();
if (dt.Rows.Count == 0)
{
GetSoftKey = false;
strSoftKey = null;
}
else
{
strSoftKey = dt.Rows[0].Field<string>("ProductKey");
GetSoftKey = true;
}
}
if ((GetSoftKey == true) && (strSoftKey != null))
{
if (strSoftKey == CommanClass.strRegkey)
{
SoftwareKey = true;
}
else
{
SoftwareKey = false;
}
}
}
catch (Exception)
{
SoftwareKey = false;
}
}
Now in When I try to write a method using entity framework for checking product key, it's confusing me at how to pass DataTable variable DataTable dt = login into entity context and set entity query parameter login.Parameter("#ProductKey", CommanClass.strRegkey), the code is
private void CheckKey()
{
try
{
using (loginEntities login = new loginEntities())
{
var pKey= from pk in login.tblSoftRegs
where pk.ProductKey == pk.ProductKey
select pk.ProductKey.FirstOrDefault();
if (pKey.Count() == 0)
{
GetSoftKey = false;
strSoftKey = null;
}
else
{
strSoftKey = ("ProductKey");
GetSoftKey = true;
}
}
if ((GetSoftKey == true) && (strSoftKey != null))
{
if (strSoftKey == CommanClass.busRegkey)
{
SoftwareKey = true;
}
else
{
SoftwareKey = false;
}
}
}
catch (Exception)
{
SoftwareKey = false;
}
}
Waiting for community contribution...
You've almost got it. FirstOrDefault will return null if there are none found, and you bind local variables directly into your LINQ query. Like this:
var pKey= from pk in login.tblSoftRegs
where pk.ProductKey == CommanClass.strRegkey
select pk.ProductKey.FirstOrDefault();
if (pKey == null)
{
GetSoftKey = false;
strSoftKey = null;
}
else
{
strSoftKey = ("ProductKey");
GetSoftKey = true;
}

How can I check new generated random in database and if it exists than again generate new in Entity Framework

var randnumber = CommonClass.Generate8DigitHBFNumber();
bool CheckCaseRef = CheckCaseRefIdAlreadyExistsInDB(randnumber);
if (CheckCaseRef)
{
randnumber = CommonClass.Generate8DigitHBFNumber();
}
else
{
randnumber = CommonClass.Generate8DigitHBFNumber();
}
//Method to Check the generated random number
bool CheckCaseRefIdAlreadyExistsInDB(string randnumber)
{
Log.Info("CheckCaseRefIdAlreadyExistsInDB started...");
bool checkCaseRef = false;
try
{
var ObjCustomerList = db.tblCustomers.ToList();
if (ObjCustomerList != null)
{
foreach (var customerlst in ObjCustomerList)
{
if (!(string.IsNullOrEmpty(randnumber)))
{
if (customerlst.CaseRef == randnumber)
{
checkCaseRef = true;
break;
}
}
}
}
else
{
return checkCaseRef;
}
}
catch (Exception ex)
{
Log.Error("Error CheckCaseRefIdAlreadyExistsInDB started...", ex);
return false;
}
return checkCaseRef;
}**
You might want to do this:
var randnumber = CommonClass.Generate8DigitHBFNumber();
while (! CheckCaseRefIdAlreadyExistsInDB(randnumber))
{
randnumber = CommonClass.Generate8DigitHBFNumber();
}
bool CheckCaseRefIdAlreadyExistsInDB(string randnumber)
{
return db.tblCustomers.Any(c => c.CaseRef == randnumber ?? "");
}
Checking the regenerated one would be an excellent use for recursion. If you don't know much about recursion, I would highly recommend doing some research on it first though, as it can lead to some really nasty memory issues in your code if used incorrectly.
//Code in main method
string randnumber = CheckRandomNumber();
//Recursive method to call
public string CheckRandomNumber()
{
string numToCheck = CommonClass.Generate8DigitHBFNumber();
if (db.tblCustomers.Any(x => x.CaseRef == numToCheck))
{
//Duplicate was found
CheckRandomNumber();
}
return numToCheck;
}

Count doesn't consider the newly inserted record

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;
}

Get the count of resultsets/Tables returned from dapper .QueryMultiple Method

While using Dapper for multiple Query:
var result = sqlConnection.QueryMultiple(query, Parameters, commandType: commandType);
How can i get the table count returned from query? It has two overloaded implementation of .Read() method, which each time called, moves to next available result set (No result.Count() property). Eventually i want to put that number in a loop to iterate as many time as number of tables returned from query.
var reader = this.DbConnection.QueryMultipleAsync(sql, Params, commandType: CommandType.StoredProcedure).Result;
if(reader.IsConsumed == false)
{
DeviceTypeReport = reader?.ReadAsync<dynamic>().Result;
}
This is probably what you are looking for hope it helps.
This is probably what you are looking for hope it helps.
List<dynamic> data = new List<dynamic>();
while (reader.IsConsumed == false)
{
data.Add(await reader?.ReadAsync<dynamic>());
}
int totalRecordSet = data.Count;
public List NotificationExecuteMultiple(OutdoorRequest objreq, IConfiguration configuration)
{
var lst = new List<dynamic>();
using (DbConnection connection = new MySqlConnection(configuration.GetConnectionString("SquareHrConn")))
{
using (var dr = connection.QueryMultiple(ProcedureName, GetParamenter(objreq), commandType: CommandType.StoredProcedure))
{
while (dr.IsConsumed == false)
{
lst.Add(dr.Read());
}
}
}
return lst;
}
Consider the follwoing method to cover all cases
protected List<object> ExecuteMultiQuery<A, B, C, D, E, F, G, H, I, J>(string procedureName, DynamicParameters param = null)
{
List<object> result = new List<object>();
using (var connection = new SqlConnection(ConnectionManager.ConnectionString))
{
try
{
connection.Open();
using (var multi = connection.QueryMultiple(procedureName, param, commandType: CommandType.StoredProcedure, commandTimeout: 120))
{
var varA = multi.Read<A>();
if (varA != null) { result.Add(varA.ToList()); }
var varB = multi.Read<B>();
if (varB != null) { result.Add(varB.ToList()); }
var varC = multi.Read<C>();
if (varC != null) { result.Add(varC.ToList()); }
var varD = multi.Read<D>();
if (varD != null) { result.Add(varD.ToList()); }
var varE = multi.Read<E>();
if (varE != null) { result.Add(varE.ToList()); }
var varF = multi.Read<F>();
if (varF != null) { result.Add(varF.ToList()); }
var varG = multi.Read<G>();
if (varG != null) { result.Add(varG.ToList()); }
var varH = multi.Read<H>();
if (varH != null) { result.Add(varH.ToList()); }
var varI = multi.Read<I>();
if (varI != null) { result.Add(varI.ToList()); }
var varJ = multi.Read<J>();
if (varJ != null) { result.Add(varJ.ToList()); }
//if (varA != null) { result.Add(varA.ToList()); }
//if (resultSets > 1) { result.Add(multi.Read<B>().ToList()); }
//if (resultSets > 2) { result.Add(multi.Read<C>().ToList()); }
//if (resultSets > 3) { result.Add(multi.Read<D>().ToList()); }
//if (resultSets > 4) { result.Add(multi.Read<E>().ToList()); }
//if (resultSets > 5) { result.Add(multi.Read<F>().ToList()); }
//if (resultSets > 6) { result.Add(multi.Read<G>().ToList()); }
//if (resultSets > 7) { result.Add(multi.Read<H>().ToList()); }
//if (resultSets > 8) { result.Add(multi.Read<I>().ToList()); }
//if (resultSets > 9) { result.Add(multi.Read<J>().ToList()); }
return result;
}
}
catch (System.Exception e)
{
string message = e.Message;
}
}
return result;
}

Categories

Resources