Azure FunctionsのNodeでSQL Serverから値を取得したメモ

## 概要

AzureのFunctionsでNodeを利用したSQL Serverへの接続をしたメモ。
async awaitを使ってConnectionをとれるようにした。
ORMapperを自前で作ってみた。
自動でやってくれるライブラリも探せばありそうだなー。


[この時点のソース](https://github.com/hibohiboo/develop/tree/bce44745ffd2071736cc5308c94b23e413a4471d/tutorial/lesson/ms-functions/ms-functions-connect-samples)

## ソース

```models/db.ts
import {Connection,Request, TYPES } from 'tedious'

let connectionInstance = null;
export const getConnection = () => new Promise<Connection>(async (resolve, reject)=>{
  if(connectionInstance) {
    resolve(connectionInstance)
  }
  try {
    connectionInstance = await createConnection()
    resolve(connectionInstance)  
  } catch (err) {
    reject(err)
  }
})

const createConnection = ()=> new Promise<Connection>((resolve, reject)=>{
  const config = {
    server: process.env["SQLConnectionServer"],
    authentication: {
        type: 'default',
        options: {
            userName: process.env["SQLConnectionUserName"],
            password: process.env["SQLConnectionUserPassword"],
        }
    },
    options: {
        database: process.env["SQLConnectionDatabase"],
        rowCollectionOnDone: true, // Requestの第二引数のrowsに値を入れるために必要
        rowCollectionOnRequestCompletion: true,  // Requestの第二引数のrowsに値を入れるために必要
    }
  }
  const connection = new Connection(config);
  connection.on('connect', function(err) {  
    if (err) {
      reject(err)
      return
    }  
    resolve(connection)
  });
})

/**
 * レコードをオブジェクトにして返す
 * @param columns レコード1行
 */
const formatORMapping = <T>(columns: any[]) => {
  const ret = {} as T
  columns.forEach(col=>{
    console.log(col)
    ret[col.metadata.colName] = col.value
  })
  return ret
}
export const read = <T>(connection: Connection, query: string) => new Promise<T[]>((resolve, reject) =>{
  const request = new Request(query, (err, rowCount, rows) => {
    if (err) {
        reject(err);
        return;
    }
    console.log(rowCount + ' row(s) returned');
    resolve(rows.map<T>(formatORMapping))
  });

  connection.execSql(request);
})
```

```models/users.ts
import * as db from './db';
interface User {
  UserID: number
  Name: string
}
export const select = async ()=>{
  const connection = await db.getConnection();
  const query = "select * from Users";
  return await db.read<User[]>(connection, query)
}
```

```index.ts
import { AzureFunction, Context, HttpRequest } from "@azure/functions"
import * as users from './models/users';

const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> {
    const responseMessage = await users.select();
    context.res = {
        body: responseMessage
    };
};
export default httpTrigger;
```


## mssqlで接続 2024.05.04 追記

[mssql](https://qiita.com/hibohiboo/items/1ad92039cb080e2ea226)
ORMapperをやってくれるライブラリ。

## 参考
[Azure Functions から SQLServerに接続する(node.js編)](https://qiita.com/ozawako1/items/c08b281fc3b2791bba6a)
[クイック スタート:Node.js を使用して Azure SQL Database または Azure SQL Managed Instance 内のデータベースに対してクエリを実行する](https://docs.microsoft.com/ja-jp/azure/azure-sql/database/connect-query-nodejs?tabs=ubuntu)
[Get started with SQL Server](https://www.microsoft.com/en-us/sql-server/developer-get-started/node/ubuntu/step/2.html)
[Tedious API](https://tediousjs.github.io/tedious/api-request.html)
[Win10 + node.js から SQL Server 2019 Express に CSVファイルを書き込んでみる 修正版(tedious-connection-pool)](https://qiita.com/tabizou/items/759105b271c419fe6683)