C#アプリケーションからPHP経由でデータベースにデータを一括登録する方法

## 背景
従来Excelで管理していたデータをデータベース管理に移行したいと思い、いろいろと調べていたのですが、WindowsアプリケーションからWeb系へアクセスするような事をされている方が少ないのか、なかなか情報が見つかりませんでした。
Excelから直接MySQLへのアクセスも検討したのですが、Excelからだと使用者のPCにODBCドライバのインストールが必要になり、PC毎にインストールをしてもらうのは大変なので、ODBCに頼らないデータ転送手法を模索しました。

## 構成
元々Excelの帳票とそれをVBAのマクロでかき集めたシートで構成していたものを、Excelの帳票を読み込み、Web経由でデータベースへ流し込むという構成を検討しました。
Excelに限らず様々なデータを転送できるようにするため、帳票の読み込みはC#のアプリケーションによって作成することにしました。
また、登録するデータは複数のレコードを一括登録するために、構造体渡しのような形をとりたく、流行りのJSONフォーマットを使用。
データの受け渡しイメージは次の通りです。
**C#アプリケーション** > **PHPページ** > **SQLデータベース**

## サンプルコード
### 送信するデータ

一括送信に使いたいデータ内容は次の通り。
元々はPOSTにてデータを渡す予定であったため、rootという頭のデータを作り、その中に実際に使用するデータを入れていますが、後述のPHP側の呼び出しでは平のデータでも大丈夫なのかもしれません。

```json:data.json
{ "root": [ { "data1": 100, "data2": "sample" } ] }
```

### 送り側処理
JSONデータを生成し、送信するためのコードです。
予めJSONで渡したいデータと同じ構造を定義し、構造体のようにセットすることでやりとりが簡単になります。
下記サンプルでは前述のように一旦rootという親を設けている関係で、データのセットは`Data`クラスで直接作成し、後で`DataContainer`にセットする形をとっています。
送信について、`WebRequest`で指定するデータの送り先は、受信処理を記述した自作のページ**regist.php**（後述）となります。
URLについてはphpコードの設置先の環境に合わせて変更してください。

```c#:sender.cs
// ===========================
// データ定義
// ===========================
[DataContract]
public class DataContainer
{
  [DataMember]
  public Data root { get; set; }
}
[DataContract]
public class Data
{
  [DataMember]
  public int data1 { get; set; }
  [DataMember]
  public string data2 { get; set; }
}

// ===========================
// 送信処理
// ===========================
private void Proc()
{
  // データの生成（実際にはフォームや帳票データからの転記）
  Data _data = new Data();
  _data.data1 = 100;       // 数値データ
  _data.data2 = "sample";  // 文字列データ

  // 送信データの生成（JSONコードへの変換）
  DataContainer _container = new DataContainer();
  _container.root = _data;
  var _serializer = new DataContractJsonSerializer(typeof(DataContainer));
  MemoryStream _stream = new MemoryStream();
  _serializer.WriteObject(_stream, _container);
  string _param = Encoding.UTF8.GetString(_stream.ToArray());
  byte[] _postData = Encoding.UTF8.GetBytes(_param);

  // 送信準備
  System.Net.WebRequest _req =
    System.Net.WebRequest.Create("http://sample.com/regist.php");
  _req.Method = "POST";
  _req.ContentType = "application/json";
  _req.ContentLength = _postData.Length;

  // 送信データの書き込み
  using(Stream _reqStream = _req.GetRequestStream())
  {
    _reqStream.Write(_postData, 0, _postData.Length);
    _reqStream.Close();
  }

  // 送信及び結果応答確認
  using(WebResponse _response = req.GetResponse())
  {
    switch(((HttpWebResponse)_response).StatusCode)
    {
      case HttpStatusCode.OK:
        // OK時の処理
        break;
      default:
        // その他の処理
        break;
    }
  }
}
```

### 受信側処理
通常POSTによって渡されたデータは`$_POST`によって受信しますが、JSON形式についてはうまく受信できないため、`file_get_contents`を使用します。
受信後のデータを`json_decode`によって連想配列に格納し利用します。

```php:regist.php
// 送信されたデータを一括受信する
$json = file_get_contents("php://input");
// 送られたデータをJSON形式として認識し、連想配列に格納
$inputs = json_decode( $json, true);
// データ登録
$sql = "insert into db_name ( data1, data2 ) values (". 
    $inputs['root']['data1']. 
    ", \"". $inputs['root']['data2']. "\")";
// SQLによるデータベースへの登録
// Query($sql);
// 応答
http_response_code(200);  // OK
```

何かのお役に立てば幸いです。

## 参考サイト
- [C#からRedmineのAPIを呼び出すのに便利なDLLモジュールを作りました。](http://shoutatani.hatenablog.com/entry/2016/05/05/181020)

- [【PHP】JSONでPOSTされた値の取り出し方。file_get_contents("php://input") するようだ。](https://qiita.com/hidepy/items/42220523cb2b3eb2c451)