Some basic information about my architecture:
- C# Web API in .Net 4.8
- Entity Framework 6.2
- Oracle database
Test case: update about 17 records in a table which consists of 1,126,126 records. Table is having primary key on Id
column.
Option 1: (Execution time ~43 seconds)
var items = _context.TRADELINEs.AsNoTracking()
.Where(x => tradelines.Keys.ToList().Contains(x.ID))
.ToList();
foreach(var i in tradelines) // tradelines is -> Dictionary<string,string> tradelines
{
string consolidateFlag = string.IsNullOrEmpty(i.Value) ? "0" : i.Value;
var newTradeline = new TRADELINE
{
ID = i.Key,
PREVCONSOLFLG = items.Where(x => x.ID == i.Key).FirstOrDefault().CONSOLFLG,
MODTS = DateTime.Now,
CONSOLFLG = consolidateFlag
};
_context.TRADELINEs.Attach(newTradeline);
_context.Entry(newTradeline).Property(x => x.PREVCONSOLFLG).IsModified = true;
_context.Entry(newTradeline).Property(x => x.CONSOLFLG).IsModified = true;
_context.Entry(newTradeline).Property(x => x.MODTS).IsModified = true;
}
_context.SaveChanges();
Option 2: (Execution time ~36 seconds)
_context.Configuration.AutoDetectChangesEnabled = false;
var items = _context.TRADELINEs.AsNoTracking()
.Where(x => tradelines.Keys.ToList().Contains(x.ID))
.ToList();
foreach(var i in tradelines) // tradelines is -> Dictionary<string,string> tradelines
{
string consolidateFlag = string.IsNullOrEmpty(i.Value) ? "0" : i.Value;
var newTradeline = new TRADELINE
{
ID = i.Key,
PREVCONSOLFLG = items.Where(x => x.ID == i.Key).FirstOrDefault().CONSOLFLG,
MODTS = DateTime.Now,
CONSOLFLG = consolidateFlag
};
_context.TRADELINEs.Attach(newTradeline);
_context.Entry(newTradeline).Property(x => x.PREVCONSOLFLG).IsModified = true;
_context.Entry(newTradeline).Property(x => x.CONSOLFLG).IsModified = true;
_context.Entry(newTradeline).Property(x => x.MODTS).IsModified = true;
}
_context.SaveChanges();
_context.Configuration.AutoDetectChangesEnabled = true;
I added the
_context.Database.Log = s => System.Diagnostics.Debug.WriteLine("SQL : " + s);
line to verify the generated SQL. In log I can see that every update statement is taking around 2-3 seconds but the same SQL statement is getting executed in few milliseconds in SQL Developer tool.
Question: Is there any way to make execution faster while using Entity Framework only? I would like to keep ExecuteSqlCommand
as the last option.
Here is the generated SQL by EF:
SQL : update "TRADELINE"
set "CONSOLFLG" = :p0, "MODTS" = :p1, "PREVCONSOLFLG" = :p2
where ("ID" = :p3)
SQL : -- :p0: '0' (Type = String, Size = 1)
SQL : -- :p1: '12/13/2019 12:09:36 PM' (Type = Date)
SQL : -- :p2: '0' (Type = String, Size = 1)
SQL : -- :p3: 'b0b2a534-db52-4dcc-b369-a5f222157d7c' (Type = String, Size = 36)
SQL : -- Executing at 12/13/2019 12:10:01 PM -06:00
SQL : -- Completed in 2538 ms with result: 1