Свойство HttpContext.Current имеет значение null в событии Sqldependency MVC

Я работаю над проектом с несколькими арендаторами, в котором у каждого арендатора есть свои клиенты. В настоящее время я реализую материал в реальном времени, в котором всякий раз, когда какой-либо клиент регистрируется или существующий клиент редактирует информацию своего профиля, я хочу уведомить арендатора этого клиента в режиме реального времени (используя signalR).

Для обнаружения изменений в таблице клиентов я использую SqlDependency и SqlTrigger. Триггер сделает запись в таблице уведомлений (которая в основном содержит некоторые идентификаторы (например, TenantId, CustomerId), на которые влияют, и некоторую другую информацию), а в событии, запущенном Sqldependency, я вызываю метод, который в дальнейшем вызывает клиентский метод, используя signalR контекст.

Теперь моя проблема в том, что я не могу получить доступ к потоку HttpContext.Current в событии Sqldependency, он имеет значение null, потому что для его выполнения не выполняется запрос. Проверьте это изображение:

введите здесь описание изображения

Пожалуйста, поправьте меня, если я ошибаюсь. Я хочу получить доступ к этому HttpContext.Current, потому что я хочу получить доступ к текущему арендатору для уведомления. И моя реализация TenantProvider получает арендатора с узла URL.

Итак, мой первый вопрос: есть ли способ получить доступ к контексту, в котором выполняется код функции события??

Если нет, то у меня есть другой вариант с некоторыми сомнениями. Вариант заключается в том, что я сохраняю таблицу изменений в уведомлениях, которая содержит информацию TenantId, CustomerId и т. д. Я могу получить доступ к уведомлению с последней отметкой времени, и из этой записи я могу получить tenantId для уведомления.

Теперь сомневаюсь, что 2 или более клиентов зарегистрируются одновременно и перед доступом к последней записи уведомления с отметкой времени вызовут ввод другого уведомления также, чем в этом случае, мы пропустили какое-то уведомление.

Так что мой второй вопрос заключается в том, думаю ли я об этом или это действительно проблема. Если это действительно проблема, пожалуйста, дайте мне знать решение ??


person Gaurav    schedule 17.04.2014    source источник
comment
К вашему сведению, я регистрирую зависимость запроса в Application_Start, поэтому решение, предложенное в ответе в stackoverflow.com/questions/8834677/ этот пост не будет работать для меня.   -  person Gaurav    schedule 17.04.2014
comment
Если каждый клиент связан ровно с одним арендатором, не можете ли вы перейти от CustomerId к TenantId через одну из ваших таблиц?   -  person zimdanen    schedule 17.04.2014
comment
Верно.. А как насчет других отношений? Может ли клиент быть частью нескольких арендаторов? Или есть прямая связь от клиента к отдельному арендатору?   -  person zimdanen    schedule 17.04.2014
comment
В яблочко. Таким образом, у одного Заказчика есть один Арендатор. Итак... где же эти отношения? В таблице?   -  person zimdanen    schedule 17.04.2014
comment
А у вас есть CustomerID в момент, когда вы пытаетесь зарегистрировать или отредактировать Заказчика?   -  person zimdanen    schedule 17.04.2014
comment
давайте продолжим это обсуждение в чате   -  person zimdanen    schedule 17.04.2014


Ответы (2)


Единственное, что меня беспокоит в том, как вы хотите это сделать, - это параллелизм ваших обновлений, именно по той причине, которую вы описываете, решение состоит в том, чтобы убедиться, что вы используете один экземпляр вашего концентратора отслеживания и параллельный словарь для ваши данные, которые вы изменяете в своем концентраторе. Вы используете таблицу уведомлений, которая на самом деле не нужна.

вот несколько ссылок для примеров, которые могут помочь вам с тем, что вы пытаетесь сделать. http://techbrij.com/database-change-notifications-asp-net-signalr-sqldependency http://www.asp.net/signalr/overview/signalr-20/getting-started-with-signalr-20/tutorial-server-broadcast-with-signalr-20

первый — это пример sqldependency, а второй — приложение в стиле концентратора центрального сервера, которое показывает, как сделать централизованный концентратор потокобезопасным.

Для проблемы с Httpcontext я использую вспомогательный класс, который я храню в своем уровне данных, я использую шаблон репозитория для разработки для одного концентратора потоков.

Вот мой класс.

using System.Web;

namespace DataLayer.Common
{
    public class ConnectionHelper : IConnectionHelper
    {
        private ApplicationDbContext _context;

        public ApplicationDbContext Context
        {
            get
            {
                if (_context == null && HttpContext.Current.Items["DbActiveContext"] != null)
                {
                    _context = (ApplicationDbContext)HttpContext.Current.Items["DbActiveContext"];
                }
                else if (_context == null && HttpContext.Current.Items["DbActiveContext"] == null)
                {
                    _context = new ApplicationDbContext();
                    HttpContext.Current.Items.Add("DbActiveContext", _context);
                }

                return _context;
            }
            set { _context = value; }
        }
    }
}
person Kelso Sharp    schedule 29.05.2014
comment
В вашем фрагменте кода предполагается, что HttpContext.Current не равен нулю. Это, в принципе, никогда не выполняется в обратном вызове уведомления. - person usr; 29.05.2014
comment
Ну, я думаю, вы что-то упустили там, я говорю об одном потоке концентратора, единственный способ, которым httpcontext.current будет нулевым, - это если вы обращаетесь к нему из другого потока, чем запрос, и если это так, вы сделали что-то не так с вашим центром отслеживания. - person Kelso Sharp; 29.05.2014
comment
Может быть, вы правы. Однако мне трудно понять, как ваш ответ решает проблему, с которой сталкивается ОП. (Я не могу вернуть -1, пока вы не отредактируете сообщение. Это правило, принудительное исполнение SO. Пожалуйста, сделайте фиктивное редактирование.) - person usr; 29.05.2014
comment
Его проблема в том, что ему нужно получить текущий контекст, и если у него есть этот класс, он может создать новый экземпляр, который будет отображаться обратно в текущий контекст, если он существует, и сможет использовать его в событии. - person Kelso Sharp; 29.05.2014
comment
И последнее, что я узнал позже... Если вы работаете в Visual Studio 2013, в Windows 8 или 8.1 HttpContext.Current всегда равен нулю. Я не уверен, является ли это ошибкой в ​​​​win 8 или она устарела и больше не используется. - person Kelso Sharp; 14.10.2014

Добавьте эти два шага, чтобы вы могли получить доступ к HttpContext.Current.Session изнутри Customer_OnChange, что, я надеюсь, приблизит вас к нужному пользовательскому контексту.

Во-первых, когда вы создаете экземпляр этого класса, сохраните HttpContext.Current.Session в свойстве. Это поможет вашему экземпляру запомнить текущий сеанс.

HttpSessionState session;
public EntityChangeNotifier()
{
    session = HttpContext.Current.Session;
}

Во-вторых, после создания экземпляра этого класса сохраните новый экземпляр как переменную сеанса. Это поддерживает экземпляр в течение всего сеанса пользователя.

EntityChangeNotifier ecn = new EntityChangeNotifier();
HttpContext.Current.Session["ecn"] = ecn;

Теперь вы можете ссылаться на свойство "session" из метода Customer_OnChange.

person Peder Benjamin Myhre    schedule 04.03.2016