Situation
I have many parameterized SQL commands. I execute these commands one after the other in a loop and looks like this:
public void SaveChanges()
{
using (var ts = _Context.Database.BeginTransaction())
{
try
{
_Context.SaveChanges();
foreach (var cmd in _Commands)
{
if (cmd.Parameter != null)
{
_Context.Database.ExecuteSqlCommand(cmd.Sql, cmd.Parameter.ToArray());
}
}
ts.Commit();
}
catch (Exception ex)
{
ts.Rollback();
throw new Exception("SaveChanges");
}
}
}
The above code works, also transcaction rollback works as expected.
My command class looks like this:
public class SqlBuilderCommand
{
public string Sql { get; set; }
public List<SqlParameter> Parameter {get;set;}
}
Possible duplicates without concrete solution
I have figured out several, possible duplicates to this question. The closest one is this:
Possible Duplicate 1
Unfortunately, it doesn't help me with the Entity Framework (or I just don't get it)
Questions
Is it possible to execute all the commands in the list in one round trip?
If not, is it possible with ADO.NET?
SOLUTION AND DRAWBACKS / LIMITATIONS
Thanks to @Evgeni for the right answer.Yes, you can concatenate many SQL-Strings and just send the parameter as a list in one round trip. That's great.
But there is a limitation with SQL-Server. SQL-Server only accepts a maximum of 2100 parameters with one command. So if you have an object with 7 database columns, the maximum bulk insert is 300 objects per command. Otherwise you get an exception.
If I do that for 5000 objects, it leads to 17 bulk inserts (5000/300). I stopped the time for 5000 objects and it is still 8-9 seconds, which is way too slow, because I know, that raw SQL will do it much, much faster.
At this point, I think there is no way around raw SQL for me, unless someone could tell me, that there is a way to speed up sql commands.
Maybe I will write a follow up question to this. Damn.
Technically you can execute multiple commands in one go:
var n1 = new SqlParameter("@name1", System.Data.SqlDbType.VarChar);
n1.Value = "name 1 ";
var u1 = new SqlParameter("@uid1", System.Data.SqlDbType.UniqueIdentifier);
u1.Value = Guid.Parse("guid here");
var n2 = new SqlParameter("@name2", System.Data.SqlDbType.VarChar);
n2.Value = "name2";
var u2 = new SqlParameter("@uid2", System.Data.SqlDbType.UniqueIdentifier);
u2.Value = Guid.Parse("guid here");
var sqlParams = new[]
{
n1, n2, u1, u2
};
using (var db = new DbContext("default"))
{
db.Database.ExecuteSqlCommand(@"
Update property set name = @name1 where uid = @uid1;
Update property set name = @name2 where uid = @uid2;", sqlParams);
}
So I'd imagine if you concatenate your sql, it should just work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With