Entity Framework: 一次往返执行多个命令
Entity Framework: Execute multiple commands in one round trip
情况
我有很多参数化的 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");
}
}
}
以上代码有效,事务回滚也按预期工作。
我的命令 class 如下所示:
public class SqlBuilderCommand
{
public string Sql { get; set; }
public List<SqlParameter> Parameter {get;set;}
}
没有具体解决方案的可能重复
我已经找出几个可能与这个问题重复的问题。最接近的是这个:
Possible Duplicate 1
不幸的是,它对我没有帮助Entity Framework(或者我就是不明白)
问题
是否可以一次来回执行列表中的所有命令?
如果不行,可以用ADO.NET吗?
解决方案和缺点/限制
感谢@Evgeni 的正确 answer.Yes,您可以连接许多 SQL-Strings 并且只需在一次往返中将参数作为列表发送。太棒了
但是 SQL-服务器有一个限制。 SQL-服务器一条命令最多只能接受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 命令。我在循环中一个接一个地执行这些命令,看起来像这样:
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");
}
}
}
以上代码有效,事务回滚也按预期工作。
我的命令 class 如下所示:
public class SqlBuilderCommand
{
public string Sql { get; set; }
public List<SqlParameter> Parameter {get;set;}
}
没有具体解决方案的可能重复
我已经找出几个可能与这个问题重复的问题。最接近的是这个:
Possible Duplicate 1
不幸的是,它对我没有帮助Entity Framework(或者我就是不明白)
问题
是否可以一次来回执行列表中的所有命令?
如果不行,可以用ADO.NET吗?
解决方案和缺点/限制
感谢@Evgeni 的正确 answer.Yes,您可以连接许多 SQL-Strings 并且只需在一次往返中将参数作为列表发送。太棒了
但是 SQL-服务器有一个限制。 SQL-服务器一条命令最多只能接受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,它应该能正常工作。