For example I am adding the peoples data to database per state (this is not what I am doing exactly but the model is same). We have list of states and each state has millions of people. So initially in code, I am saving the state to get the State ID and then use that ID to bulk insert peoples data.
If something goes wrong while adding the peoples data, let's say 20th million record threw some exception, is there a way to revert back the data already saved in both Peoples and State table?
Any suggestion is highly appreciated..
List <Peoples> PeopleList = new List<Peoples>();
int peopleCounter = 0;
foreach (var stateVal in States)
{
using (var context = new StateEntities())
{
State st = new State();
st.ID = stateVal.ID;
st.Name = stateVal.Name;
context.State.Add(st);
context.SaveChanges();
if (stateVal.Peoples != null )
{
foreach (var _p in stateVal.Peoples)
{
Peoples _people = new Peoples();
_people.Name = _p.Name;
_people.Age = _P.Age;
_people.State_ID = stateVal.ID; // Getting state ID from State object as it already saved to DB
PeopleList.Add(_people)
peopleCounter++;
if (peopleCounter == 100000)
{
InsertPeople(PeopleList, context); // does bulk insert when PeopleList reaches 100k
PeopleList.Clear();
peopleCounter = 0;
}
}
}
}
}
private static void InsertPeople(List<Peoples> PeopleList, StateEntities context)
{
context.Configuration.AutoDetectChangesEnabled = false;
context.Configuration.ValidateOnSaveEnabled = false;
using (var transactionScope = new TransactionScope(TransactionScopeOption.Required, new System.TimeSpan(0, 30, 0)))
{
context.BulkInsert(PeopleList, options => options.BatchTimeout = 0);
context.SaveChanges();
transactionScope.Complete();
}
}
You can use transaction of SQL to rollback. It's supported by EF.
using (var context = new SchoolContext())
{
using (DbContextTransaction transaction = context.Database.BeginTransaction())
{
try
{
//**TODO: Do your bulk insert codes here**
// Save changes data in context
context.SaveChanges();
// Commit changes
transaction.Commit();
}
catch (Exception ex)
{
// Rollback all changes
transaction.Rollback();
}
}
}
Ref: https://learn.microsoft.com/en-us/ef/core/saving/transactions
Related
What does the Rollback method in EF Core do? If I didn't use Commit, I don't need it anyway. If I used Commit, the transaction has already been completed.
using (var context = new AppDbContext())
{
using (var transaction = context.Database.BeginTransaction())
{
try
{
var myObjectOne = new MyObjectOne() { Name = "Book" };
context.MyObjectOnes.Add(myObjectOne);
context.SaveChanges();
var myVal = myObjectOne.Id * 3.14;
var myObjectTwo = new MyObjectTwo() { Name = "Notebook", Price = 100, ReferenceId = myVal };
context.MyObjectTwos.Add(myObjectTwo);
context.SaveChanges();
transaction.Commit();
}
catch (Exception ex)
{
transaction.Rollback();
}
}
}
What does the RollBack Method do? C# EF Core.
Is this a good way to set the transaction level to serializable? If I set a lower transaction level, I will get duplicate orders. What is better approach? I assume this method will be invoked frequently by different users.
Here is my code
using (var tran = context.Database.BeginTransaction(IsolationLevel.Serializable))
{
try
{
var lastDocument = context.Documents.OrderByDescending(x => x.Id).FirstOrDefault();
int order = 1;
if (lastDocument != null)
{
order = lastDocument.Order + 1;
}
var document = new Document
{
CreatedDate = DateTimeOffset.UtcNow,
Name = Guid.NewGuid().ToString(),
Order = order
};
context.Documents.Add(document);
context.SaveChanges();
tran.Commit();
}
catch (Exception ex)
{
tran.Rollback();
}
}
I am an old hand at ADO.NET but new to linq. I have written the below function to change one column of int in the database to a new value. The query part works fine, but after me updating the KeyStates in the database doesn't seem to work. Nothing changes. No errors, but also no update.
public static void UpdateKeySetToDatabase(IChangeTrackableAsSet set,
int tableId, State newState)
{
try
{
using (var c = new SqlConnection(ConnectionString.ConnectionString))
{
c.Open();
List<int> keyList = set.trackedKeys.Select(k => k.KeyId).ToList();
DataContext dc = new DataContext(c);
Table<TrackedKey> tableKeys = dc.GetTable<TrackedKey>();
var KeyStates =
from k in tableKeys
where (keyList.Contains(k.KeyId) && k.TableId == tableId)
select k;
foreach (var k in KeyStates)
{
EventHandling.Logging.CreateTextEvent($"Key {k.ShowKeyAsJson()}");
k.StatusOfKey = (int)newState;
EventHandling.Logging.CreateTextEvent($"New Key {k.ShowKeyAsJson()}");
};
tableKeys.Context.SubmitChanges();
}
}
catch (Exception ex)
{
EventHandling.Logging.CreateTextEvent($"linq error {ex.ToString()}");
}
}
I think you should specify to the Entity Framework context, that the entity has changed, in order to update it.
...
k.StatusOfKey = (int)newState;
EventHandling.Logging.CreateTextEvent($"New Key {k.ShowKeyAsJson()}");
dc.Entry(k).State = EntityState.Modified;
...
When you execute the SaveChanges() method, all your objects will be modified.
The data is inserted using LINQ to SQL, the id is generated but the database table is empty.
Using a stored procedure there is no problem. But inserting using linq the id is generated everytime but the table is empty.
The code is below:
Int32 t = 2;
using (EduDataClassesDataContext db =new EduDataClassesDataContext())
{
using (var scope = new TransactionScope())
{
db.Connection.ConnectionString = Common.EdukatingConnectionString;
UserLogin userlog = new UserLogin();
userlog.Username = userinfo.Username;
userlog.Password = userinfo.Password;
userlog.UserTypeId = t;
userlog.FullName = userinfo.FullName;
db.UserLogins.InsertOnSubmit(userlog);
db.SubmitChanges();
Int64 n = userlog.Id;
UserInformation userinfor = new UserInformation();
userinfor.FirstName = userinfo.FirstName;
userinfor.LastName = userinfo.LastName;
userinfor.MobileNum = userinfo.MobileNum;
userinfor.Email = userinfo.Email;
userinfor.Gender = userinfo.Gender;
userinfor.Address = userinfo.Address;
userinfor.UserLoginId = n;
userinfor.CreatedBy = n;
userinfor.OrganizationName = userinfo.OrganizationName;
userinfor.DateOfBirth = userinfo.DateOfBirth;
userinfor.CreatedDate = DateTime.Now;
db.UserInformations.InsertOnSubmit(userinfor);
db.SubmitChanges();
}
}
When you are using a TransactionScope, you need to call the Complete method in order to Commit the transaction in the DataBase.
using (var db = new EduDataClassesDataContext())
using (var scope = new TransactionScope())
{
...
db.UserInformations.InsertOnSubmit(userinfor);
db.SubmitChanges();
// The Complete method commits the transaction. If an exception has been thrown,
// Complete is not called and the transaction is rolled back.
scope.Complete();
}
Failing to call this method aborts the transaction, because the
transaction manager interprets this as a system failure, or exceptions
thrown within the scope of transaction.
I am using session.query,first time its return latest database records and we populate on grid after editing on fields we save on database and then we again execute this query then it is not getting the updated record from database. the fields has updated in database but not getting updated record.
My NHibernate query is given below
List<FiscalPeriod> lstPeriods = new List<FiscalPeriod>();
using (var tr = session.BeginTransaction())
{
try
{
List<TSCFiscalPeriod> lstFiscalPeriods = session.Query<TSCFiscalPeriod>().ToList();
if (lstFiscalPeriods != null && lstFiscalPeriods.Count > 0)
{
foreach (var period in lstFiscalPeriods)
{
FiscalPeriod objPeriod = new FiscalPeriod();
objPeriod.Period = period.Id.FPeriod;
objPeriod.Name = "Period " + objPeriod.Period;
objPeriod.CompanyID = period.Id.FCompanyID;
objPeriod.Year = period.Id.FFiscalYear;
objPeriod.Begin = period.FBeginDate;
objPeriod.End = period.FEndDate;
objPeriod.OpenAP = FOpenAP(period.FOpen);
objPeriod.OpenGL = FOpenGL(period.FOpen);
objPeriod.SCFiscalPeriod = period;
objPeriod.IsExisting = true;
lstPeriods.Add(objPeriod);
}
}
tr.Commit();
}
catch (Exception ex)
{
lstPeriods = null;
CusException cex = new CusException(ex);
cex.Write();
}
return lstPeriods;
}
Is there any refresh method or something i am doing wrong.
Any help will be appreciated.thanks
make sure you are using session.clear() or session.flush() after save the session.
Nhibernate session is a static initializer.
Sometimes session is not able to refresh values.
So You have to flush and clear the session
session.flush();
session.clear();