Как разрешить SignalR загружать обновления из БД в браузер, используя EF6 - PullRequest
2 голосов
/ 27 октября 2019

Как разрешить SignalR загружать обновления из SQLServer DB в браузер, используя EF6.

Вот мой метод действия:

public ActionResult Index()
        {
            var currentGates = _ctx.Transactions
                                                .GroupBy(item => item.SubGateId)
                                                .SelectMany(group => group.OrderByDescending(x => x.TransactionDateTime)
                                                .Take(1))
                                                .Include(g => g.Card)
                                                .Include(g => g.Student)
                                                .Include(g => g.Student.Faculty)
                                                 .Include(g => g.Student.Department)
                                                .Include(g => g.SubGate)
                                                .ToList();


            return View(currentGates);
        }

Через многопоиска только один результат, который я получаю:

ASP.NET MVC 5 SignalR, SqlDependency и EntityFramework 6

Я пробовал предложенный способ, но он не работали в дополнение к этому я обнаружил очень важную проблему безопасности, связанную с хранением конфиденциальных данных в скрытом поле!

Мой вопрос:

Как обновить свое представление в соответствии с любым Insert в таблице транзакций?

Ответы [ 3 ]

5 голосов
/ 30 октября 2019

Итак, в общем, вам нужно переписать метод SaveChanges() и действие, которое вы выполняете с помощью функции SignalR:

public class ApplicationDbContext : IdentityDbContext<IdentityUser>
  {
  public override int SaveChanges()
        {
            var entities = ChangeTracker.Entries().Where(x => x.Entity is Transactions && x.State == EntityState.Added) ;
            IHubContext hubContext = GlobalHost.ConnectionManager.GetHubContext<MyHub>();
            foreach (var entity in entities)
            {
              hubContext.Clients.All.notifyClients(entity);
            }

            return base.SaveChanges();
         }
    }
1 голос
/ 05 ноября 2019

Обычно я подключаюсь либо к службе, создающей транзакцию, либо к событию Сохранить изменения, например @Vince. Однако из-за вашего нового требования

проблема заключается в следующем: у меня нет этого контроля надsdk, который переводит транзакции студентов в db, поэтому я надеюсь, что есть какой-то способ работать непосредственно над таблицей db.

В вашем случае вы можете просто просмотреть таблицу, используя зависимости SQL

Примечание: будьте осторожны, используя SqlDependency класс - у него проблемы с утечками памяти.

using(var tableDependency = new SqlTableDependency<Transaction>(conString))
{
    tableDependency.OnChanged += TableDependency_Changed;
    tableDependency.Start();
}

void TableDependency_Changed(object sender, RecordChangedEventArgs<Transaction> e)
{
    if (e.ChangeType != ChangeType.None)
    {
        var changedEntity = e.Entity;
        //You'll need to change this logic to send only to the people you want to 
        IHubContext hubContext = GlobalHost.ConnectionManager.GetHubContext<MyHub>();
        hubContext.Clients.All.notifyClients(entity);
    }
}

Редактировать Кажется, у вас могут быть другие зависимости, например, вы хотите включить в свои результаты. Итак, что вы можете сделать, это разрешить Id из сущности, а затем вызвать Get используя EntityFramework.

if (e.ChangeType != ChangeType.None)
{
    var changedEntity = e.Entity;
    var id = GetPrimaryKey(changedEntity)
    _ctx.Transactions.Find(id);
}

Edit Другие методы подхода.

  1. Если у ваших сущностей есть последнее обновленное поле, вы можете сканировать изменения в таблице по таймеру. У клиента есть таймер, по истечении которого он отправляет последний раз, когда проверял изменения. Сервер получает все объекты, у которых время последнего обновления больше, чем время, прошедшее в

  2. Хотя у вас нет доступа к EF, у вас, вероятно, есть доступ к сетиAPI-запросы. Когда кто-то вызывает метод обновления или создания, просто захватите идентификатор измененного объекта, вставьте все идентификаторы объектов, измененных в фоновую службу, которая будет отправлять уведомления сигнализатора,

единственной проблемой сейчас является получение первичного ключа, что можно сделать с помощью ручного сопоставления типов с их свойством id, или это можно сделать с использованием метаданных из модели, но это немного сложнее

Обратите внимание, что вы, вероятно,можно изменить так, чтобы он работал в общем случае на всех таблицах

1 голос
/ 05 ноября 2019

Я понимаю, что у вас есть следующий поток данных:

  • 6x устройства считывания карт
  • 'менеджер' получает данные устройства считывания карт и переводит их в
  • aТаблица транзакций SQLServer

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

Таким образом, проблема в том, что ваша служба ASP.net должна быть уведомлена об изменениях вотслеживаемая таблица базы данных.

Быстрый и грязный подход:

  1. реализует триггер базы данных в вашей большой таблице транзакций, которая обновляет облегченную таблицу состояний
  2. CREATE TABLE state( GateId INT NOT NULL, UserName VARCHAR (20) NOT NULL, PRIMARY KEY (GateId)); Эта таблица предназначена для записи только 1 записи на каждый шлюз. 6 ворот -> 6 записей в этой таблице.
  3. Измените службу ASP.net, чтобы опросить таблицу состояний за интервал, например, 200 мс. Делая такой взлом, убедитесь, что в таблице, которую вы опрашиваете, не много записей! Как только вы обнаружите изменение, сообщите об этом своим клиентам SignalR.

ИМХО, поток данных через базу данных - плохое проектное решение (или ограничение). Было бы намного лучше, если бы ваш «менеджер» не только отправлял данные в базу данных, но впоследствии уведомлял всех клиентов SignalR. Этот поток данных в основном соответствует тому, что предполагает ответ @Vince.

Редактировать: Поскольку вы опубликовали фактическое устройство, которое вы используете, я рекомендую вам перепроверить, если вы можете напрямую подключиться ккард-ридер. Похоже, что есть способы зарегистрировать какой-то обратный вызов, когда устройство прочитало студенческий билет. Делайте это с единственной целью - получить такой строгий поток данных / архитектуру, как это:

  -> connect 6x card readers to your 
  -> ASP.Net service which at a single point in your code:
        -> updates the database
        -> updates the Signal R clients
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...