简体   繁体   English

实体框架:一次往返执行多个命令

[英]Entity Framework: Execute multiple commands in one round trip

Situation 情况

I have many parameterized SQL commands. 我有许多参数化的SQL命令。 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 可能重复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? 如果不是,是否可以使用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. 感谢@Evgeni的正确答案。是的,您可以连接许多SQL字符串,并且只需一次往返就可以将参数作为列表发送。 That's great. 那很棒。

But there is a limitation with SQL-Server. 但是SQL-Server有一个限制。 SQL-Server only accepts a maximum of 2100 parameters with one command. SQL-Server仅通过一个命令最多接受2100个参数。 So if you have an object with 7 database columns, the maximum bulk insert is 300 objects per command. 因此,如果您的对象具有7个数据库列,则每个命令的最大批量插入量为300个对象。 Otherwise you get an exception. 否则,您将获得例外。

If I do that for 5000 objects, it leads to 17 bulk inserts (5000/300). 如果我对5000个对象执行此操作,则会导致17个大容量插入(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. 我停止了5000个对象的时间,但仍然是8到9秒,这太慢了,因为我知道原始SQL会更快得多。

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. 在这一点上,我认为对我而言,没有办法解决原始SQL,除非有人告诉我,有一种方法可以加快sql命令的速度。

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. 因此,我想如果您将sql连接起来,它应该可以正常工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM