C# 在ASP.NET MVC中使用临时表 背景:

C# 在ASP.NET MVC中使用临时表 背景:,c#,tsql,asp.net-mvc-3,C#,Tsql,Asp.net Mvc 3,我目前正在编写一个web前端,用于分析插入SQL Server的web日志 最基本的功能之一是,您可以通过指定一个时间范围(这通常是一个用于排除最近流量故障的工具,而不是深度数据挖掘)和其他各种字段(如ClientIP、Uri等)来搜索一组结果 我最初是用LINQ做的,但开始对它感到恼火,并决定对我来说用StringBuilder构造查询和使用它会更容易。所以我仍然使用为我的表生成的dmbl(实际上有31个表,每天一个,但视图将它们组合在一起)。然后在我的控制器中创建如下查询: public A

我目前正在编写一个web前端,用于分析插入SQL Server的web日志

最基本的功能之一是,您可以通过指定一个时间范围(这通常是一个用于排除最近流量故障的工具,而不是深度数据挖掘)和其他各种字段(如ClientIP、Uri等)来搜索一组结果

我最初是用LINQ做的,但开始对它感到恼火,并决定对我来说用StringBuilder构造查询和使用它会更容易。所以我仍然使用为我的表生成的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);
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())
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;
其中Where子句是基于传递给控制器的GET参数生成的,类似于:

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);
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())
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;
UberRows只是拥有
公共列表行我只是用jquery和DataTable插件在div中呈现结果,因为结果集通常应该很小

现在,我的问题是: 我还希望他的一系列查询能够查询上述搜索的结果集(每个服务器的点击次数、平均响应时间等)

我猜这样做的方法是创建一个包含结果的临时表(因为如果我不这样做,我将不得不为每个查询生成基本结果,比如结果集的响应时间),但是因为我不熟悉这一点,c#,而asp.mvc我也不确定它是如何工作的,是否与mvc、我的ORM和dmbl类联系在一起。假设我对临时表的看法是正确的,我将如何处理它

因此,纯SQL将类似于:

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);
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())
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;

临时表不会持续超过创建它的DB会话。全局临时表可以跨DB会话共享,但根据您的场景,会话开始和结束时可能无法预测,因此可能无法给出可预测的结果

我建议创建一个真实的表来保存结果,并对其进行查询。查询完成后,只需删除所有数据。如果可以使用不同的结果集进行多个连接(因此临时表非常好),那么可以添加一个UNIQUEIDENTIFIER字段作为用于此查询集的数据集的“键”。也就是说,在应用程序端生成GUID,并将其传递到填充实际表的查询中,以便针对它的每个查询都可以使用应用程序生成的值作为附加WHERE子句。对该“临时”结果集的所有查询完成后,基于该GUID执行删除。如果由于某种原因,针对特定结果集的查询被断开,并且您不知道最后一个查询何时执行,请向结果集添加一个DATETIME字段,并创建一个SQL代理作业,以删除超过30或60分钟或其他时间的记录

编辑:
另外,要明确的是,如果所有查询都是由单个连接完成的,那么如果启用MARS(多个活动结果集),您可能仍然可以使用临时表,因为我认为MARS保持一致的会话,但我不确定,因为我从未使用过它。

是动态查询,还是您提前定义的查询?如果内存中有数据,只需使用LINQ执行定义的查询即可。如果你愿意解析表达式树,你甚至可以做动态的。@Tejs:更新了我的问题,说明了各种where子句是如何生成的——所以我相信如果这就是你的意思的话,它是动态的。此外,我认为在这一点上,如果可以的话,我想继续使用我的StringBuilder。我建议看看bltoolkit——比微软的任何标准linnq实现都快得多,非常适合这种任务。啊,听起来是个好主意。我现在不打算接受,只是想看看我的其他选择是什么。。。我甚至都没有考虑到会议的复杂性。