Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework: Execute multiple commands in one round trip

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

  1. Is it possible to execute all the commands in the list in one round trip?

  2. 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.

like image 876
Michael Avatar asked Mar 10 '23 19:03

Michael


1 Answers

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.

like image 149
Evgeni Avatar answered Mar 12 '23 09:03

Evgeni