Работа с временными таблицами в ASP.NET MVC

#c# #tsql #asp.net-mvc-3

#c# #tsql #asp.net-mvc-3

Вопрос:

Предыстория:

В настоящее время я пишу веб-интерфейс для анализа наших веб-журналов, которые вставляются в SQL Server.

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

Изначально я делал это с помощью LINQ, но это начало меня раздражать, и я решил, что для меня было бы проще создавать запросы с помощью StringBuilder и использовать Dapper.NET. Итак, я все еще вижу dmbl, созданный для моей таблицы (на самом деле существует 31 таблица, по одной на каждый день, но представление объединяет их). А затем создайте запросы в моем контроллере, которые выглядят примерно так:

 public ActionResult Index(SearchParams sp)
{

    var db = new LogTableDataContext();
    var query = new StringBuilder();
    ...
    var fields = " Time, ClientIp, Method, Uri, Bytes, Server, Tr, TermState, UserAgent, Host ";
    query.Append(" SELECT ");

    if (sp.top.HasValue)
        query.Append(" Top ").Append(sp.top);
    query.Append(fields);
    query.Append(" from Logs ");

    query.Append(" WHERE 1=1 ");
    if (wherestrings.HasValue())
        query.Append(wherestrings);
    var resultsModel = new UberRows { rows = results, generated_query = query.ToString(), query_params = sp.GetPropertyNamesAndValues() };
    return View(resultsModel);
  

Где Предложения WHERE генерируются на основе параметров GET, передаваемых контроллеру, что-то вроде:

 public string GenerateWhereString()
{
    var wherestring = new StringBuilder();
    if (this.Uri.HasValue())
        wherestring.Append(" AND Uri = @Uri ");
    if (this.ClientIp.HasValue())
        wherestring.Append(" AND ClientIp = @ClientIP ");
    if (this.Server.HasValue())
  

UberRows просто имеет public List<HAProxyLogViewer.Log> rows; , и я просто отображаю результаты в div с помощью jquery и плагина DataTable, поскольку результирующие наборы обычно должны быть небольшими.

Теперь, к моему вопросу:

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

Я предполагаю, что способ сделать это — создать временную таблицу с результатами (поскольку, если бы я этого не сделал, мне пришлось бы генерировать базовые результаты для каждого из этих запросов по таким параметрам, как время отклика для результирующего набора), но поскольку я новичок в этом, c # и asp.mvc, я не уверен ни в общей картине того, как это будет работать, ни в привязке к MVC, моему ORM и классам dmbl. Предполагая, что я прав относительно временной таблицы, как я буду с этим работать?

Таким образом, чистый SQL был бы чем-то вроде:

 SELECT Time, ClientIp, Method, Uri, Bytes, Server, Tr, TermState, UserAgent, Host
INTO #resultsTable 
FROM Logs
WHERE 1=1 AND Time BETWEEN dateadd(minute, -1440, getutcdate()) and getutcdate()
AND UserAgent = 'Mozilla/5.0 (compatible; Googlebot/2.1;  http://www.google.com/bot.html)';

SELECT Time, ClientIp, Method, Uri, Bytes, Server, Tr, TermState, UserAgent, Host
FROM #resultsTable;

SELECT Server, COUNT(*)
FROM #resultsTable
GROUP BY Server;

SELECT AVG(Tr)
FROM #resultsTable;

DROP TABLE #resultsTable;
  

Комментарии:

1. Это динамические запросы или запросы, которые вы определяете заранее? Если у вас есть данные в памяти, вы можете просто выполнять определенные запросы с помощью LINQ. Вы даже можете создавать динамические таблицы, если хотите анализировать деревья выражений.

2. @Tejs: Обновил мой вопрос относительно того, как генерируются различные предложения where — поэтому я считаю, что это динамично, если вы это имеете в виду. Кроме того, я думаю, что на данный момент я хотел бы придерживаться моего StringBuilder, если смогу.

3. Ой. Я предлагаю взглянуть на bltoolkit — намного быстрее, чем любая стандартная реализация linnq от Microsoft, и идеально подходит для такого рода задач.

Ответ №1:

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

Я бы предложил создать реальную таблицу для хранения результатов и просто запросить ее. Когда запросы будут выполнены, просто УДАЛИТЕ все данные. Если возможно иметь несколько подключений с использованием разных наборов результатов (следовательно, временная таблица была бы отличной), то вы можете добавить поле UNIQUEIDENTIFIER в качестве «ключа», для какого набора данных использовать для этого набора запросов. То есть сгенерируйте GUID на стороне приложения и передайте его в запрос, который заполняет реальную таблицу, чтобы каждый из запросов к ней мог использовать это сгенерированное приложением значение в качестве дополнительного предложения WHERE. Когда все запросы к этому «временному» результирующему набору будут выполнены, выполните УДАЛЕНИЕ на основе этого GUID. Если по какой-то причине запросы к определенному результирующему набору отключены, и вы не знаете, когда выполняется последний, добавьте поле DATETIME в результирующий набор и создайте задание агента SQL для удаления записей старше 30 или 60 минут или чего-то еще.

Редактировать: Также, для ясности, если все запросы действительно выполняются с помощью одного соединения, то вы могли бы по-прежнему использовать временную таблицу, если вы включите MARS (Несколько активных наборов результатов), поскольку я думаю, что MARS поддерживает согласованный сеанс, но я не уверен, поскольку я никогда им не пользовался.

Комментарии:

1. А, это звучит как хорошая идея. Пока не собираюсь соглашаться, просто чтобы посмотреть, какие у меня есть другие варианты… Я даже не думал об осложнениях сеанса.