Я надеюсь создавать некоторый материал агрегирования данных в C#, и я хотел бы что-то сродни сводной таблице в реальном времени или своего рода непрерывно обновляющий SQL-запрос, с поддержкой select
, sum
, average
, first
, where
, и group-by
(где first
находится в смысле LINQ, "дают мне первое значение").
Например, у меня мог бы быть своего рода названный объект таблицы Trans
со столбцами Name
, Date
, и Total
, и другая названная таблица Price
со столбцами Name
и Price
. Я хочу создать своего рода Query
экземпляр, который делает (в псевдо-SQL)
select Name, sum(Total), first(Price) from Trans, Price join on Name group by Name
и передача это к Aggregator
экземпляр, который имеет ссылки на источники данных. Наряду с этим я хочу зарегистрировать обратный вызов, который поражен каждый раз, когда строка, что запрос вызывает изменения. Таким образом, если бы цена за объект под названием изменения 'XYZ', обратный вызов инициировал бы с объектом, содержащим новые значения для той агрегированной строки. Я также хотел бы Aggregator
быть максимально эффективным, таким образом, это имело бы своего рода схему индексации, таким образом, это не должно будет к сканированию таблицы каждый раз, когда измененные значения.
Я не совсем уверен, что назвать этот вид вещи, и я надеюсь смочь реализовать что-то полностью в C#, предполагая, что это не порядок величины, более сложный, чем я думаю, что это могло бы быть. Я читал о Непрерывном LINQ и Связываемом LINQ, но я не мог действительно распознаться, если или соответствия эта проблема, или если будут проблемы производительности (например, перечисление агрегирований LINQ через всю таблицу каждый раз, когда значение изменяется).
Кто-либо знает о проекте, который делает что-то вроде этого, что я мог посмотреть на или иметь предложения о том, как разработать/создать его сам?
править: Я должен отметить, что данные на самом деле не были бы в базе данных, это будет в памяти.
Вы видели Push Linq или Reactive Extensions (Rx) ?
Хотя я не использовал ни то, ни другое, я считаю, что оба позволяют использовать операторы LINQ о потоковой передаче данных.
Дополнительную информацию о Rx можно найти на сайте DevLabs:
Первым альтернативным решением является агрегирование с использованием изменений базовых данных - т.е. когда я обновляю запись итогов, я обновляю и итоговую сумму. Однако, чтобы сделать это таким образом, вам понадобится старое значение, кроме того, это добавляет накладные расходы на любые изменения, которые вы вносите в агрегированные значения. Но если вся цель существующих данных - быть агрегированными, это может быть жизнеспособным вариантом.
Я делаю это в своем приложении для балансировки банковских счетов, каждый раз, когда я вставляю/изменяю/удаляю транзакцию, логика также обновляет баланс счета, потому что баланс перебирается много раз и вскоре может стать дорогим для вычисления, когда есть много транзакций.
Я думаю, что структурно у вас тоже могут возникнуть проблемы, если суммы будут храниться в базе данных - например, проблемы с блокировкой. Я бы всегда хранил эти значения в памяти.
Update: другое возможное решение - передать код доступа к данным через слой обслуживания, который хранит агрегированные значения в памяти - это будет очень быстро и практически без накладных расходов на вставку/обновление/удаление базовых данных. Можно также поступить умнее и сделать этот слой транзакционным, чтобы в случае сбоя действия доступа к данным можно было откатить изменение агрегации.
Единственным недостатком является то, что изменения в базе данных должны проходить через этот слой, чтобы избежать недействительности агрегации, и ему потребуется инициализация из базы данных при первом запуске или перезапуске.