Я использую EF5
для переноса некоторых данных из одной базы данных в другую. Я бы обычно использовал SQL
для чего-то подобного, но мне нужны другие функции (например, создание пользователей в MembershipProvider
) и надеялся сделать все это в EF. Я мигрируют около 100к строк и использовать это, чтобы сделать это:EntityFramework Операция ожидания, рассчитанная по длительной задаче
using (var connection = new SqlConnection(connectionString))
{
using(var command = new SqlCommand(commandText, connection))
{
connection.Open();
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
var employer = new Employer();
employer.EAN = reader["EAN"].ToString();
employer.Name = GetString(reader["EmpName"]);
employer.TaxMailingAddress = new Address
{
StreetAddress = GetString(reader["Street"]),
City = GetString(reader["City"]),
State = GetString(reader["USState"]),
ZipCode = GetString(reader["Zip"])
};
employer.TaxMailingAddress.SaveOrUpdate();
employer.SaveOrUpdate(); // This is where the timeout happens
string dba = GetString(reader["DBA"]);
if (!string.IsNullOrWhiteSpace(dba))
{
employer.AddDBA(new EmployerDba
{
Name = dba
});
}
string email = GetString(reader["Email"]);
if (!string.IsNullOrWhiteSpace(email))
{
var user = CreateNewUser(email);
if (user != null)
{
user.AddAuthorizedEmployer(employer);
user.AddRole(EmployerRole.Admin, employer, true);
}
}
}
}
}
}
Мой SaveOrUpdate
метод довольно прост:
public void SaveOrUpdate()
{
using (var db = new MyContext())
{
if (db.Employers.FirstOrDefault(x => x.EAN == EAN && x.Id != Id) != null)
throw new Exception("An employer with this EAN has already been registered.");
var employer = new Employer();
if (Id == 0)
{
db.Employers.Add(employer);
employer.CreatedBy = Statics.GetCurrentUserName();
employer.DateCreated = DateTime.Now;
}
else
{
employer = db.Employers.FirstOrDefault(x => x.Id == Id);
employer.ModifiedBy = Statics.GetCurrentUserName();
employer.DateModified = DateTime.Now;
}
employer.EAN = EAN;
employer.Name = Name;
if (TaxMailingAddress != null) employer.TaxMailingAddress = db.Addresses.FirstOrDefault(x => x.Id == TaxMailingAddress.Id);
if (SingleSeparationStatementAddress != null) employer.SingleSeparationStatementAddress = db.Addresses
.FirstOrDefault(x => x.Id == SingleSeparationStatementAddress.Id);
db.SaveChanges();
Id = employer.Id;
}
}
Задача должна занять около 2,5 часов. Тем не менее, после запуска многих тысяч строк, иногда 80k, иногда до 7k, я получаю это исключение "The wait operation timed out"
, всегда на employer.SaveOrUpdate();
. Может ли это иметь какое-либо отношение к тому, насколько близко к employer.TaxMailingAddress.SaveOrUpdate();
? Есть ли «дождаться завершения транзакции»? Возможно, убедитесь, что соединение действительно, и если вы не пытаетесь воссоздать его или что-то еще? Спасибо за любую помощь.
По умолчанию для любых команд, запускаемых с БД, есть таймаут 30/60 секунд. Вы можете переопределить этот параметр в своем DbContext. См. Http://stackoverflow.com/questions/10549640/how-to-set-commandtimeout-for-dbcontext. Тем не менее, делать такие вещи в чистом EF - не самая лучшая идея. – Kittoes0124
@ Kittoes +1 EF добавляет огромные накладные расходы на ваш процесс. Каждый кусок передаваемых данных собирается использовать память, поскольку она преобразуется в объект. – Aron
Да, хотя EF является одним из моих любимых инструментов, когда-либо созданных, у него все еще есть время и место. Бывают случаи, когда я загружаю данные, подобные этим, но они всегда являются одноразовыми сценариями. Процессы, подобные описанным выше, НИКОГДА не должны вносить его в производство. – Kittoes0124