46
loading...
This website collects cookies to deliver better user experience
DbContext.SaveChanges
which was neither saving changes to the database nor throwing any exceptions, and after solving the issue I found it interesting to list some of the reasons that might cause this issue and how to detect them.DbContext
is saving it somewhere else. For example the connection string is not the one you expect. It's a common mistake that some developers change the connection string in the configuration file of the data access project instead of the startup project.// check the value of the connection string
string connection = dbContext.Database.GetConnectionString();
dbContext.SaveChanges();
var mapping = dbContext.Model.FindEntityType(typeof(YourEntity));
string schema = mapping.GetSchema();
string table = mapping.GetTableName();
dbContext.SaveChanges();
schema
and table
are as you expect.SaveChanges
on a different instance of your DbContext
, and that might not be easy to spot in some complex codebases where changes to the DbContext
are far from the call to SaveChanges
.DbContext
instance which could be used to check that.dbContext.Employees.Add(newEmp);
string id1 = dbContext.ContextId;
.....
// elsewhere in the codebase
string id2 = dbContext.ContextId;
dbContext.SaveChanges();
id1
equals id2
.SaveChangeAsync
without awaiting it (i.e. using await keyword) which absorbs exceptions and obviously to fix that you just need to await the call await dbContext.SaveChangesAsync();
.bool hasChanges = dbContext.ChangeTracker.HasChanges(); // should be true
int updates = dbContext.SaveChanges(); // should be > 0
hasChanges
is false or updates
is 0 then the Change Tracker couldn't detect your changes, maybe because you're changing the value of a NotMapped
property like FullName
in the entity below.public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
[NotMapped]
public string FullName { get; set; }
}
db.Entry(myEntity).State = EntityState.Modified; // use an appropriate state
dbContext.SaveChanges();
hasChanges
equals true, updates
will be greater than 0) and the SQL Server Profiler will show that the insert statement executed successfully on your database but still you won't find any changes, check this.using (var context = new MyContext())
{
var transaction = context.Database.BeginTransaction(IsolationLevel.Serializable);
context.Employees.Add(newEmployee);
int updates = context.SaveChanges(); // updates == 1 even when the transaction is not committed
}
SaveChange
wasn't working and the BeginTransaction
call was not as clear as in the above snippet, it was buried into a forsaken area in the codebase, where someone was trying something and forgot to remove it.DbContext
has a current transaction you can check if context.Database.CurrentTransaction
is not null.// use this to check if a database transaction has begun
var hasTransaction = context.Database.CurrentTransaction != null;
context.SaveChanges();
hasTransaction
is true you should commit your transaction by calling transaction.Commit
after calling SaveChanges
, otherwise your changes will not be saved.using (var context = new MyContext())
{
var transaction = context.Database.BeginTransaction(IsolationLevel.Serializable);
context.Employees.Add(newEmployee);
int updates = context.SaveChanges();
transaction.Commit(); // solves the problem
}
Disable Trigger All on YourTableName
Disable Trigger All on Database.
SP:StmtStarting
and SP:StmtCompleted
events are selected in the "Trace Properties" dialog.SP:StmtStarting
and SP:StmtCompleted
events.datetime
field in MS SQL Server which has less precision than the DateTime
object in .NET, check the code below.myEntity.Time = DateTime.Parse("2020–01–01 13:45:59.2501234"); // the last 4 digits will never be saved
dbContext.SaveChanges();
exec sp_executesql N'SET NOCOUNT ON;
UPDATE [MyTable] SET [Time] = @p0
WHERE [Id] = @p1;
SELECT @@ROWCOUNT;
',N'@p1 int,@p0 datetime',@p1=1,@p0='2020–01–01 13:45:59.250'
DateTime
object. Note that this issue is one of the issues that can be spotted via the SQL Server profiler.