Обновить данные из хранимой процедуры
У меня есть приложение фреймворка сущности С#.
Я пытаюсь запустить хранимую процедуру из кода (без проблем). его длительный ход, около 30 минут. Я записываю журнал каждой транзакции в таблицу SQL по мере прохождения процесса.
Я ищу, чтобы начать процедуру из приложения, но затем показать последние 10 записей журнала на экране, может быть, запрос каждые 10 секунд. это покажет прогресс.
private void Window_Loaded_1(object sender, RoutedEventArgs e)
{
Task.Run(() => _serviceProduct.RefreshAllAsync());
_cvsLog = (CollectionViewSource)(FindResource("cvsLog"));
var dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
dispatcherTimer.Interval = TimeSpan.FromSeconds(10);
dispatcherTimer.Start();
}
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
_cvsLog.Source = _serviceProduct.GetRefreshLog();
}
Я изменил код, чтобы упростить. Поток блокирует процесс dispatcherTime_Tick. Похоже, что хранимая процедура не работает.
Здесь вызывается служба.
public ObservableCollection<RefreshLog> GetRefreshLog()
{
using (var db = new HiggidyPiesEntities())
{
var recs = (from x in db.RefreshLogs orderby x.LG_ID descending select x).Take(30);
var obs = new ObservableCollection<RefreshLog>(recs);
return obs;
}
}
Я был на рабочем пути работника и task.run, но процедура продолжает блокировать поток.
Я даже подумал о том, чтобы инициировать SQL-задание из кода, а затем отслеживать журнал после этого с помощью вызовов в базе данных.
Может быть, услуга-брокер может быть выбор?
любые мысли о том, с какой дорогой я должен пойти с этим типом проблемы?
заранее спасибо Скотт
Ответы
Ответ 1
Учитывая природу этих данных, являющихся просто статусом для пользователя, кажется, что делать READ UNCOMMITTED. Вы можете попробовать эти два варианта, оба из которых выглядят довольно прямолинейно:
Прежде всего, нужно установить свойство Session/Connection:
public ObservableCollection<RefreshLog> GetRefreshLog()
{
using (var db = new HiggidyPiesEntities())
{
db.context.ExecuteStoreCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;");
var recs = (from x in db.RefreshLogs orderby x.LG_ID descending select x).Take(30);
var obs = new ObservableCollection<RefreshLog>(recs);
return obs;
}
}
Во-вторых, попробуйте настроить уровень изоляции транзакций через EF:
public ObservableCollection<RefreshLog> GetRefreshLog()
{
using (var scope = new TransactionScope(TransactionScopeOption.Required,
new TransactionOptions() {
IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted
}))
{
ObservableCollection<RefreshLog> obs;
using (var db = new HiggidyPiesEntities())
{
var recs =
(from x in db.RefreshLogs orderby x.LG_ID descending select x).Take(30);
obs = new ObservableCollection<RefreshLog>(recs);
}
scope.Complete();
return obs;
}
}
Обе идеи взяты из разных ответов на этот вопрос: Entity Framework с NOLOCK. Первое предложение, основанное на ответе Фрэнка.Гермена, второе на основе слова Александра.
И только для того, чтобы он упоминался как опция, вы можете посмотреть в функции SNAPSHOT ISOLATION, которая была представлена в SQL Server 2005:
Ответ 2
Если вы используете EF 6.0 и .NET 4.5, вы должны попробовать использовать последнюю функцию и поддержку acync: Анимационный запрос Entity Framework 6, Поддержка асинхронных шаблонов на основе задач в EF
Похоже, что эта функция предназначена именно для ваших и подобных проблем.
Вы можете объединить его с DispatcherTimer
, предложенным @user2002076.
Чтобы прочитать, что вы прогрессируете каждые x секунд, вы можете разработать другую хранимую процедуру, и внутри вы можете намекать на SQL с READ UNCOMMITTED.
Очевидно, все это требует EF 6.0 и .NET 4.5, но реализация будет приятной и короткой.