C# 实体框架:在一次往返中执行多个命令

C# 实体框架:在一次往返中执行多个命令,c#,sql-server,entity-framework,command,roundtrip,C#,Sql Server,Entity Framework,Command,Roundtrip,形势 我有许多参数化的SQL命令。我在循环中一个接一个地执行这些命令,如下所示: public void SaveChanges() { using (var ts = _Context.Database.BeginTransaction()) { try { _Context.SaveChanges(); foreach (var cmd in _Commands) {

形势

我有许多参数化的SQL命令。我在循环中一个接一个地执行这些命令,如下所示:

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");
        }
    }
}
public class SqlBuilderCommand
{
    public string Sql { get; set; }

    public List<SqlParameter>  Parameter {get;set;}
}
上述代码可以正常工作,Transaction回滚也可以正常工作

我的命令类如下所示:

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");
        }
    }
}
public class SqlBuilderCommand
{
    public string Sql { get; set; }

    public List<SqlParameter>  Parameter {get;set;}
}
公共类SqlBuilderCommand
{
公共字符串Sql{get;set;}
公共列表参数{get;set;}
}
没有具体解决方案的可能重复项

我已经找出了这个问题的几个可能的重复之处。最接近的是:

不幸的是,它对实体框架没有帮助(或者我就是不明白)

问题

  • 是否可以在一次往返中执行列表中的所有命令

  • 如果没有,是否可以使用ADO.NET

  • 解决方案和缺点/限制

    感谢@Evgeni给出了正确的答案。是的,您可以连接许多SQL字符串,只需在一次往返过程中将参数作为列表发送。太好了

    但是SQL Server有一个限制。SQL Server一个命令最多只能接受2100个参数。因此,如果您有一个包含7个数据库列的对象,则每个命令的最大批量插入量为300个对象。否则你会得到一个例外

    如果对5000个对象执行此操作,将导致17个批量插入(5000/300)。我停止了5000个对象的时间,但仍然是8-9秒,这太慢了,因为我知道,原始SQL会做得更快

    在这一点上,我认为没有办法绕过原始SQL,除非有人告诉我,有一种方法可以加速SQL命令


    也许我会就此写一个后续问题。该死。

    从技术上讲,您可以一次执行多个命令:

        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);
        }
    

    所以我想,如果您连接sql,它应该可以正常工作。

    您完全可以用sql参数替换字符串。我会更新代码…啊啊啊啊啊啊啊,现在我明白了,你想向我解释什么。我将在周末评估这个解决方案,因为我今天和明天都没有时间。从这里看很有希望。如果合适,我会将你的答案标记为有效,并将我的答案张贴在问题中。谢谢你,叶甫盖尼!这是正确的答案。我现在唯一的问题是,SQL Server的最大参数数是每个命令2100个。因此,如果您有一个包含7个数据库列的对象,则可以使用一个命令发送max 300。对于5000次插入,我停止了8秒的时间,在我看来这仍然是缓慢的。我认为没有办法绕过原始SQL。我查看了第三方库,它可以处理EF的批量插入,并且它们还生成原始SQL。无论如何,你的回答绝对正确。谢谢你的帮助!我还写了问题的解决方案和局限性。