SQL Server 2017 に、バイナリデータを保存する

令和2年3月13日金曜日。日中暖かい。報道によると、靖国神社のソメイヨシノの標本木が一輪、二輪、咲きだしたとか。
明日には、桜の開花宣言が出されるかもしれない。天気予報によると、雪の予報が出ている。
去年の今頃は、新聞配達のバイトにチャレンジしていたと思う。
デビュー戦、酷い雨で、先輩に頑張って付いて行ったことを思い出す。

Dicomファイルの管理に、データベースを使おうと思い立って、色々調べた。
意外にやろうと思っていることがそっくりそのまま出ていたので引用させてもらう。
①接続文字列
②テーブルの定義
③コード
ポイントはこの三つになるだろうと思う。


①接続文字列

string strConn = @"Data Source=192.168.0.1;Initial Catalog=DICOM;User=******;Password=******;";
接続先は、リモートホストのSQL Server 2017 Express。
SQL Server 認証を想定している。
ミニマルで上記の接続文字列が必要。Windows 認証用の文字列が入り込んでいると、Windows 認証として接続が認識されてしまうらしく、
蹴られる。このミニマルの接続で確からしいので、ココから出発してもらいたい。

②テーブルの定義

バイナリーデータを格納するフィールドは、VARBINARY(MAX)と定義する。

CREATE TABLE [dbo].[dcmfiles]
(
[Id] INT NOT NULL PRIMARY KEY,
[dcm] VARBINARY(MAX) NULL
)

③コード

                
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Data.SqlClient;
using System.Data;

namespace BLOB
{
    class Program
    {
        static void Main(string[] args)
        {
            Insert(1);

            GetByID(1);
        }

        static void Insert(int id_int)
        {
            string dcmPath = @"temp.dcm";

            System.IO.FileInfo fi = new System.IO.FileInfo(dcmPath);
            long size = fi.Length;
;
            byte[] dcm_blob = new byte[(int)size];

            using(FileStream fs = new FileStream(dcmPath, FileMode.Open))
            {
                for (int i = 0; i < size; i++)
                {
                    dcm_blob[i] = (byte)fs.ReadByte();
                }
            }

            Console.WriteLine("Hello");

            string strConn = @"Data Source=192.168.0.1;Initial Catalog=DICOM;User=******;Password=******;";

            SqlConnection cnn = new SqlConnection(strConn);
            SqlCommand cmd = new SqlCommand();

            cmd.Connection = cnn;
            cmd.CommandText = "insert into koneko values(@Id,@dcm)";

            SqlParameter id = new SqlParameter("@Id", id_int);
            SqlParameter dcm = new SqlParameter("@dcm", SqlDbType.VarBinary);
            dcm.Value = dcm_blob;

            cmd.Parameters.Add(id);
            cmd.Parameters.Add(dcm);

            cnn.Open();
            cmd.ExecuteNonQuery();
            cnn.Close();                      
        }

        public static void GetByID(int photoid)
        {
            string strConn = @"Data Source=192.168.0.1;Initial Catalog=DICOM;User=******;Password=******;";

            SqlConnection cnn = new SqlConnection(strConn);
            SqlCommand cmd = new SqlCommand();
            byte[] data = new byte[1000];

            cmd.CommandText = "select * from koneko where Id = @Id";
            cmd.Connection = cnn;

            SqlParameter pId = new SqlParameter("@Id", photoid);
            cmd.Parameters.Add(pId);

            cnn.Open();
            SqlDataReader reader = cmd.ExecuteReader();

            MemoryStream ms = new MemoryStream();

            int index = 0;

            using (FileStream fs = new FileStream("koneko.dcm", FileMode.Create))
            {
                while (reader.Read())
                {
                    while (true)
                    {
                        long count = reader.GetBytes(reader.GetOrdinal("dcm"), index, data, 0, data.Length);

                        if (count == 0)
                        {
                            break;
                        }
                        else
                        {
                            index = index + (int)count;
                            ms.Write(data, 0, (int)count);

                            fs.Write(data, 0, (int)count);
                            Console.Write(ms);
                        }
                    }
                }
            }

            cnn.Close();

        }
    }
}