【问题标题】:Entity Framework: Execute multiple commands in one round trip实体框架:一次往返执行多个命令
【发布时间】:2017-07-11 09:24:21
【问题描述】:

情况

我有许多参数化的 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;}
}

没有具体解决方案的可能重复

我已经想出了这个问题的几个可能的重复项。最接近的是这样的:

Possible Duplicate 1

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

问题

  1. 是否可以一次往返执行列表中的所有命令?

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

解决方案和缺点/限制

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

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

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

在这一点上,我认为对我来说没有办法绕过原始 SQL,除非有人能告诉我,有一种方法可以加快 sql 命令的速度。

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

【问题讨论】:

    标签: c# sql-server entity-framework command roundtrip


    【解决方案1】:

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

        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参数替换字符串。我会更新代码...
    • Aaaaahhh,现在我明白了,你试图向我解释什么。我将在本周末评估此解决方案,因为我今天和明天都没有时间。从这里看起来很有希望。如果合适,我会将您的答案标记为有效并在问题中发布我的解决方案。谢谢叶甫根尼!
    • 这是正确的答案。我现在唯一的问题是,SQL-Server 的最大参数数是每个命令 2100。因此,如果您有一个包含 7 个数据库列的对象,您可以使用一个命令发送最多 300 个。对于 5000 次插入,我停止了 8 秒的时间,我认为这仍然很慢。我认为没有办法绕过原始 SQL。我查看了第三方库,它可以处理 EF 的批量插入,并且它们还生成原始 SQL。无论如何 - 你的答案是绝对正确的。感谢您的帮助!
    • 我在问题中也写了解决方案和限制。
    猜你喜欢
    • 2011-01-21
    • 1970-01-01
    • 1970-01-01
    • 2019-03-25
    • 2019-08-06
    • 1970-01-01
    • 2011-02-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多