Useless connection opening/closing in Linq query
Posted: Sun 12 Aug 2012 10:28
-----------------------------------------------------
Here is the code:
/*
"Entities" is a DbContext Entity class (using EntityFramework.4.3.1).
SMS is an entity with members ID (Entity Key), TEL, DATE, BODY, etc.
*/
First version:
using (Entities ctxt = new Entities())
{
foreach (FileInfo fi in arr)
{
SMS rec = new SMS();
rec.FromFile(fi);
var q = from r in ctxt.SMSs
where r.TEL == rec.TEL && r.DATE == rec.DATE
select r;
int N = q.Count();
if (N == 0)
ctxt.SMSs.Add(rec);
}
try
{
ctxt.SaveChanges();
}
catch (Exception ex)
{
// ...
}
}
Second version:
using (Entities ctxt = new Entities())
{
// Open connection for RecCountOf() calls
sqLiteCommand1.Connection = (Devart.Data.SQLite.SQLiteConnection) ctxt.Database.Connection;
sqLiteCommand1.Connection.Open();
foreach (FileInfo fi in arr)
{
SMS rec = new SMS();
rec.FromFile(fi);
if (RecCountOf(rec) == 0)
ctxt.SMSs.Add(rec);
}
try
{
ctxt.SaveChanges();
}
catch (Exception ex)
{
// ...
}
}
private int RecCountOf(SMS rec)
{
// sqLiteCommand1.CommandText is "SELECT COUNT(*) FROM SMS WHERE TEL = :TEL AND DATE = :DATE"
sqLiteCommand1.Parameters["TEL"].Value = rec.TEL;
sqLiteCommand1.Parameters["DATE"].Value = rec.DATE;
SQLiteDataReader sqReader = sqLiteCommand1.ExecuteReader();
int N = 0;
try
{
sqReader.Read();
N = sqReader.GetInt32(0);
}
finally
{
sqReader.Close();
}
return N;
}
-----------------------------------------------------
The first version is slow, the second one very fast (~2000 imported records).
Why?
dbMonitor shows that every time the Linq query is executed, a new connection is opened then closed.
Opening ctxt.Database.Connection before entering the loop does not seem to solve the problem.
Is there a workaround?
Here is the code:
/*
"Entities" is a DbContext Entity class (using EntityFramework.4.3.1).
SMS is an entity with members ID (Entity Key), TEL, DATE, BODY, etc.
*/
First version:
using (Entities ctxt = new Entities())
{
foreach (FileInfo fi in arr)
{
SMS rec = new SMS();
rec.FromFile(fi);
var q = from r in ctxt.SMSs
where r.TEL == rec.TEL && r.DATE == rec.DATE
select r;
int N = q.Count();
if (N == 0)
ctxt.SMSs.Add(rec);
}
try
{
ctxt.SaveChanges();
}
catch (Exception ex)
{
// ...
}
}
Second version:
using (Entities ctxt = new Entities())
{
// Open connection for RecCountOf() calls
sqLiteCommand1.Connection = (Devart.Data.SQLite.SQLiteConnection) ctxt.Database.Connection;
sqLiteCommand1.Connection.Open();
foreach (FileInfo fi in arr)
{
SMS rec = new SMS();
rec.FromFile(fi);
if (RecCountOf(rec) == 0)
ctxt.SMSs.Add(rec);
}
try
{
ctxt.SaveChanges();
}
catch (Exception ex)
{
// ...
}
}
private int RecCountOf(SMS rec)
{
// sqLiteCommand1.CommandText is "SELECT COUNT(*) FROM SMS WHERE TEL = :TEL AND DATE = :DATE"
sqLiteCommand1.Parameters["TEL"].Value = rec.TEL;
sqLiteCommand1.Parameters["DATE"].Value = rec.DATE;
SQLiteDataReader sqReader = sqLiteCommand1.ExecuteReader();
int N = 0;
try
{
sqReader.Read();
N = sqReader.GetInt32(0);
}
finally
{
sqReader.Close();
}
return N;
}
-----------------------------------------------------
The first version is slow, the second one very fast (~2000 imported records).
Why?
dbMonitor shows that every time the Linq query is executed, a new connection is opened then closed.
Opening ctxt.Database.Connection before entering the loop does not seem to solve the problem.
Is there a workaround?