Entity Framework: выполнение нескольких команд в одном цикле
ситуация
У меня много параметризованных команд 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;}
}
Возможные дубликаты без конкретного решения
Я выяснил несколько возможных дубликатов этого вопроса. Наиболее близким является это:
К сожалению, это не помогает мне с Entity Framework (или я просто не понимаю)
Вопросы
Можно ли выполнить все команды в списке за один круг?
Если нет, возможно ли это с ADO.NET?
РЕШЕНИЕ И НЕДОСТАТКИ / ОГРАНИЧЕНИЯ
Спасибо @Evgeni за правильный ответ. Да, вы можете объединить множество SQL-строк и просто отправить параметр в виде списка за один цикл. Замечательно.
Но есть ограничение с SQL-сервером. SQL-Server принимает максимум 2100 параметров с помощью одной команды. Поэтому, если у вас есть объект с 7 столбцами базы данных, максимальная массовая вставка составляет 300 объектов на команду. В противном случае вы получите исключение.
Если я сделаю это для 5000 объектов, это приведет к 17 объемным вставкам (5000/300). Я остановил время для 5000 объектов, и это все еще 8-9 секунд, что слишком медленно, потому что я знаю, что сырой SQL сделает это намного, намного быстрее.
На данный момент, я думаю, что нет никакого способа обойти необработанный SQL для меня, если кто-то не может сказать мне, что есть способ ускорить команды sql.
Возможно я напишу дополнительный вопрос к этому. Черт.
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, он должен просто работать.