2017-10-18 5 views
0

ジオコーディングの目的でAPIを呼び出すSSISジョブにc#スクリプトタスクがあります。 APIはプロプライエタリであり、このように動作し、要求を受け取り、アドレス文字列を受け取り、巨大なアドレスリスト(数百万)に文字列を一致させようとします。見つからない場合は、googleやgeodataなどの別のサービスに行きます情報このC#HttpWebRequestをどのように高速化できますか?

この文字列のマッチングは、リクエストごとに多くの時間がかかります。時には1分あたり1リクエストと同じくらい遅いですが、これを行うために必要な4Mのアドレスがあります。 APIサイドで開発作業を行うことはオプションではありません。

私は、データベースから(約4M)アドレスのリストを引っ張ると変数データテーブルに入れて設定します:

​​

をここでの処理のより良い画像を与えるためには、私が現在やっているものですGetGLFromAddress()は次のようになります。

上記の変数を使用してJSONを作成します。 "POST"とhttpWebRequestを使用してJSONを送信します。リクエストを待つ(時間がかかる)。返信要求。戻り値で新しい変数を設定します。これらの変数を使用してデータベースに更新/挿入し、元のデータテーブルの次の行をループします。

localIDを各リクエストごとに可変にする必要があるため、このフローを理解することが重要です。データベースの正しいレコードを更新できるようにします。

はここGetGLFromAddress()です:

私は Parallel.Foreachを使用しようとしました
private void GetGLFromAddress() 
    { 
     // Request JSON data with Payload 
     var httpWebRequest = (HttpWebRequest)WebRequest.Create("http:"); 
     httpWebRequest.Headers.Add("Authorization", ""); 
     httpWebRequest.ContentType = "application/json"; 
     httpWebRequest.Method = "POST"; 

     using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream())) 
     { 
      // this takes the variables from your c# datatable and formats them for json post 
      var jS = new JavaScriptSerializer(); 
      var newJson = jS.Serialize(new SeriesPost() 
      { 
       AddressLine1 = address, 
       City   = city, 
       StateCode = state, 
       CountryCode = country, 
       PostalCode = zip, 
       CreateSiteIfNotFound = true 
      }); 


      //// So you can see the JSON thats output 
      System.Diagnostics.Debug.WriteLine(newJson); 
      streamWriter.Write(newJson); 
      streamWriter.Flush(); 
      streamWriter.Close(); 

     } 

     try 
     { 
      var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse(); 
      using (var streamReader = new StreamReader(httpResponse.GetResponseStream())) 
      { 
       var result = streamReader.ReadToEnd(); 
       // javascript serializer... deserializing the returned json so that way you can set the variables used for insert string 
       var p1 = new JavaScriptSerializer(); 

       // after this line, obj is a fully deserialzed string of json Notice how I reference obj[x].fieldnames below. If you ever want to change the fiels or bring more in 
       // this is how you do it. 
       var obj = p1.Deserialize<List<RootObject>>(result); 

       // you must ensure the values returned are not null before trying to set the variable. You can see when that happens, I'm manually setting the variable value to null. 
       if (string.IsNullOrWhiteSpace(obj[0].MasterSiteId)) 
       { 
        retGLMID = "null"; 
       } 
       else 
       { 
        retGLMID = obj[0].MasterSiteId.ToString(); 
       } 

       if (string.IsNullOrWhiteSpace(obj[0].PrecisionName)) 
       { 
        retAcc = "null"; 
       } 
       else 
       { 
        retAcc = obj[0].PrecisionName.ToString(); 
       } 

       if (string.IsNullOrWhiteSpace(obj[0].PrimaryAddress.AddressLine1Combined)) 
       { 
        retAddress = "null"; 
       } 
       else 
       { 
        retAddress = obj[0].PrimaryAddress.AddressLine1Combined.ToString(); 
       } 

       if (string.IsNullOrWhiteSpace(obj[0].Latitude)) 
       { 
        retLat = "null"; 
       } 
       else 
       { 
        retLat = obj[0].Latitude.ToString(); 
       } 

       if (string.IsNullOrWhiteSpace(obj[0].Longitude)) 
       { 
        retLong = "null"; 
       } 
       else 
       { 
        retLong = obj[0].Longitude.ToString(); 
       } 
       retNewRecord = obj[0].IsNewRecord.ToString(); 

       // Build insert string... notice how I use the recently created variables 
       // string insertStr = retGLMID + ", '" + retAcc + "', '" + retAddress + "', '" + retLat + "', '" + retLong + "', '" + localID; 
       string insertStr = "insert into table  " + 
            "(ID,GLM_ID,NEW_RECORD_IND,ACCURACY) " + 
            " VALUES          " + 
            "('" + localID + "', '" + retGLMID + "', '" + retNewRecord + "', '" + retAcc + "')"; 


       string connectionString = "Data Source=; Initial Catalog=; Trusted_Connection=Yes"; 
       using (SqlConnection connection = new SqlConnection(connectionString)) 
       { 
        SqlCommand cmd = new SqlCommand(insertStr); 
        cmd.CommandText = insertStr; 
        cmd.CommandType = CommandType.Text; 
        cmd.Connection = connection; 
        connection.Open(); 
        cmd.ExecuteNonQuery(); 
        connection.Close(); 
       } 
      } 
     } 

     { 
      string insertStr2 = "insert into table " + 
           "(ID,GLM_ID,NEW_RECORD_IND,ACCURACY) " + 
           " VALUES          " + 
           "('" + localID + "', null, null, 'Not_Found')"; 
      string connectionString2 = "Data Source=; Initial Catalog=; Trusted_Connection=Yes"; 

      using (SqlConnection connection = new SqlConnection(connectionString2)) 
      { 
       SqlCommand cmd = new SqlCommand(insertStr2); 
       cmd.CommandText = insertStr2; 
       cmd.CommandType = CommandType.Text; 
       cmd.Connection = connection; 
       connection.Open(); 
       cmd.ExecuteNonQuery(); 
       connection.Close(); 
      } 
     } 
    } 

、私は変数の問題を持っていました。私は複数の要求を走らせたいと思っていますが、それが理にかなっていれば、リクエストごとに変数の各インスタンスを保持することができます。 localIDをAPIに渡して返す方法がないか、それが理想的です。

これも可能ですか?

そして、私が何を達成するためにこの呼び出しを構造化する必要がありますか?

私は基本的に、複数の呼び出しを送信して、プロセス全体を高速化したいと考えています。

EDIT:GetGlFromAddress()のコードを追加しました。はい、私はnewbですので、親切にしてください:)

答えて

0

一度に複数のリクエストを呼び出すことができます。複数のタスクや非同期メソッドを使用してAPIを呼び出すことをお勧めします。

+0

私はすべての要求文字列を配列に入れて、例えばAとBの2つしか書けません。私はAとBを送り、Bが最初に戻ります。データベースの正しいレコードを確実に更新するにはどうすればよいですか? Asyncは物事が正しい順序で返されるようにする方法がありますか?マルチスレッドはどうですか? – user3486773

関連する問題