创建一个应用来运行基本查询

适用于:✅Azure 数据资源管理器

在本文中,学习如何:

先决条件

设置开发环境以使用 Kusto 客户端库。

运行基本查询并处理结果

在首选 IDE 或文本编辑器中,使用适合首选语言的约定创建名为“基本查询”的项目或文件。 然后,添加以下代码:

  1. 创建连接到帮助群集的客户端应用。

    using Kusto.Data;
    using Kusto.Data.Net.Client;
    
    namespace BasicQuery {
      class BasicQuery {
        static void Main(string[] args) {
          var clusterUri = "https://help.chinaeast2.kusto.chinacloudapi.cn/";
          var kcsb = new KustoConnectionStringBuilder(clusterUri)
              .WithAadUserPromptAuthentication();
    
          using (var kustoClient = KustoClientFactory.CreateCslQueryProvider(kcsb)) {
          }
        }
      }
    }
    
  2. 定义要运行的数据库和查询。 该查询返回导致总损失超过 1 亿美元的龙卷风的发生日期、州和总损失。

    var database = "Samples";
    var query = @"StormEvents
                  | where EventType == 'Tornado'
                  | extend TotalDamage = DamageProperty + DamageCrops
                  | summarize DailyDamage=sum(TotalDamage) by State, bin(StartTime, 1d)
                  | where DailyDamage > 100000000
                  | order by DailyDamage desc";
    
  3. 运行查询并输出结果。

    using (var response = kustoClient.ExecuteQuery(database, query, null)) {
      int columnNoStartTime = response.GetOrdinal("StartTime");
      int columnNoState = response.GetOrdinal("State");
      int columnNoDailyDamage = response.GetOrdinal("DailyDamage");
      Console.WriteLine("Daily tornado damages over 100,000,000$:");
    
      while (response.Read()) {
        Console.WriteLine("{0} - {1}, {2}",
          response.GetDateTime(columnNoStartTime),
          response.GetString(columnNoState),
          response.GetInt64(columnNoDailyDamage));
      }
    }
    

完整代码应如下所示:

using Kusto.Data;
using Kusto.Data.Net.Client;

namespace BasicQuery {
  class BasicQuery {
    static void Main(string[] args) {
      string clusterUri = "https://help.chinaeast2.kusto.chinacloudapi.cn/";
      var kcsb = new KustoConnectionStringBuilder(clusterUri)
          .WithAadUserPromptAuthentication();

      using (var kustoClient = KustoClientFactory.CreateCslQueryProvider(kcsb)) {
        string database = "Samples";
        string query = @"StormEvents
                         | where EventType == 'Tornado'
                         | extend TotalDamage = DamageProperty + DamageCrops
                         | summarize DailyDamage=sum(TotalDamage) by State, bin(StartTime, 1d)
                         | where DailyDamage > 100000000
                         | order by DailyDamage desc";

        using (var response = kustoClient.ExecuteQuery(database, query, null)) {
          int columnNoStartTime = response.GetOrdinal("StartTime");
          int columnNoState = response.GetOrdinal("State");
          int columnNoDailyDamage = response.GetOrdinal("DailyDamage");

          Console.WriteLine("Daily tornado damages over 100,000,000$:");

          while (response.Read()) {
            Console.WriteLine("{0} - {1}, {2}",
              response.GetDateTime(columnNoStartTime),
              response.GetString(columnNoState),
              response.GetInt64(columnNoDailyDamage));
          }
        }
      }
    }
  }
}

运行应用

在命令行界面中,使用以下命令运行应用:

# Change directory to the folder that contains the basic queries project
dotnet run .

你应会看到如下所示的结果:

Daily damages tornado with damages over 100,000,000$:
2007-02-02 00:00:00+00:00 - FLORIDA , 270004000 $
2007-03-01 00:00:00+00:00 - ALABAMA , 266853000 $
2007-05-04 00:00:00+00:00 - KANSAS , 251625000 $
2007-03-01 00:00:00+00:00 - GEORGIA , 143688000 $

使用序号位置访问列值

当查询结果中的列顺序已知时,按列在结果集中的序号位置访问列值比按列名访问列值更为有效。 (可选)在运行时,可以使用库方法根据列名确定列序号。

注意

可以使用 projectproject-away 运算符控制查询结果中列的呈现和顺序。

例如,可以修改上面的代码,以按结果集中的序号位置访问 StartTimeStateDailyDamage 列的值:

在 C# 中,只能按列在结果集中的序号位置访问列值。 不能使用列名;因此代码保持不变。

int columnNoStartTime = response.GetOrdinal("StartTime");
int columnNoState = response.GetOrdinal("State");
int columnNoDailyDamage = response.GetOrdinal("DailyDamage");
Console.WriteLine("Daily tornado damages over 100,000,000$:");

while (response.Read()) {
  Console.WriteLine("{0} - {1}, {2}",
    response.GetDateTime(columnNoStartTime),
    response.GetString(columnNoState),
    response.GetInt64(columnNoDailyDamage));
}

使用客户端请求属性自定义查询行为

可以通过设置客户端请求属性来自定义查询的行为。 有关可用选项的详细信息,请参阅客户端请求属性

例如,可以替换上面代码中的 kusto_client.execute_query 调用以传递自定义请求 ID,并将查询超时设置为 1 分钟。 若要使用客户端请求属性,必须导入 ClientRequestProperties 类。

using Kusto.Data.Common;

var crp = new ClientRequestProperties();
// Set a custom client request identifier
crp.ClientRequestId = "QueryDemo" + Guid.NewGuid().ToString();
// Set the query timeout to 1 minute
crp.SetOption(ClientRequestProperties.OptionServerTimeout, "1m");

using (var response = kustoClient.ExecuteQuery(database, query, crp)) {
}

使用查询参数保护用户输入

查询参数对于维持数据安全性和保护非常重要。 它们可以防范潜在的恶意行动者未经授权访问或损坏数据。 有关参数化查询的详细信息,请参阅查询参数声明语句

例如,可以修改上面的代码,以将 EventType 值和 DailyDamage 最小值作为参数传递给查询。 若要使用参数,请执行以下操作:

  1. 在查询文本中声明参数
  2. 将参数名称替换为查询文本中的属性值
  3. 在传递给 execute 方法的客户端请求属性中设置参数值
string query = @"declare query_parameters(event_type:string, daily_damage:int);
                  StormEvents
                  | where EventType == event_type
                  | extend TotalDamage = DamageProperty + DamageCrops
                  | summarize DailyDamage=sum(TotalDamage) by State, bin(StartTime, 1d)
                  | where DailyDamage > daily_damage
                  | order by DailyDamage desc";

var crp = new ClientRequestProperties();
crp.SetParameter("event_type", "Flash Flood");
crp.SetParameter("daily_damage", 200000000.ToString());

using (var response = kustoClient.ExecuteQuery(database, query, crp)) {
  int columnNoStartTime = response.GetOrdinal("StartTime");
  int columnNoState = response.GetOrdinal("State");
  int columnNoDailyDamage = response.GetOrdinal("DailyDamage");
  Console.WriteLine("Daily flash flood damages over 200,000,000$:");

  while (response.Read()) {
    Console.WriteLine("{0} - {1}, {2}",
      response.GetDateTime(columnNoStartTime),
      response.GetString(columnNoState),
      response.GetInt64(columnNoDailyDamage));
  }
}

使用序号位置访问列值和参数的完整代码如下所示:

using Kusto.Data;
using Kusto.Data.Common;
using Kusto.Data.Net.Client;

namespace BasicQuery {
  class BasicQuery {
    static void Main(string[] args) {
      string clusterUri = "https://help.chinaeast2.kusto.chinacloudapi.cn/";
      var kcsb = new KustoConnectionStringBuilder(clusterUri)
          .WithAadUserPromptAuthentication();

      using (var kustoClient = KustoClientFactory.CreateCslQueryProvider(kcsb)) {
        string database = "Samples";
        string query = @"declare query_parameters(event_type:string, daily_damage:int);
                         StormEvents
                         | where EventType == event_type
                         | extend TotalDamage = DamageProperty + DamageCrops
                         | summarize DailyDamage=sum(TotalDamage) by State, bin(StartTime, 1d)
                         | where DailyDamage > daily_damage
                         | order by DailyDamage desc";

        var crp = new ClientRequestProperties();
        crp.ClientRequestId = "QueryDemo" + Guid.NewGuid().ToString();
        crp.SetOption(ClientRequestProperties.OptionServerTimeout, "1m");
        crp.SetParameter("event_type", "Flash Flood");
        crp.SetParameter("daily_damage", 200000000.ToString());

        using (var response = kustoClient.ExecuteQuery(database, query, crp)) {
          int columnNoStartTime = response.GetOrdinal("StartTime");
          int columnNoState = response.GetOrdinal("State");
          int columnNoDailyDamage = response.GetOrdinal("DailyDamage");

          Console.WriteLine("Daily flash flood damages over 200,000,000$:");

          while (response.Read()) {
            Console.WriteLine("{0} - {1}, {2}",
              response.GetDateTime(columnNoStartTime),
              response.GetString(columnNoState),
              response.GetInt64(columnNoDailyDamage));
          }
        }
      }
    }
  }
}

你应会看到如下所示的结果:

Daily flash flood damages over 200,000,000$:
2007-08-21 00:00:00+00:00 - OHIO , 253320000 $

下一步