#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. А, это звучит как хорошая идея. Пока не собираюсь соглашаться, просто чтобы посмотреть, какие у меня есть другие варианты… Я даже не думал об осложнениях сеанса.