F# で SQLServer StoredProc を実行する次のコードを書きました。
module SqlUtility =
open System
open System.Data
open System.Data.SqlClient
SqlUtility.GetSqlConnection "MyDB"
|> Option.bind (fun con -> SqlUtility.GetSqlCommand "dbo.usp_MyStordProc" con)
|> Option.bind (fun cmd ->
let param1 = new SqlParameter("@User", SqlDbType.NVarChar, 50)
param1.Value <- user
cmd.Parameters.Add(param1) |> ignore
let param2 = new SqlParameter("@PolicyName", SqlDbType.NVarChar, 10)
param2.Value <- policyName
cmd.Parameters.Add(param2) |> ignore
Some(cmd)
)
|> Option.bind (fun cmd -> SqlUtility.ExecuteReader cmd)
|> Option.bind (fun rdr -> ExtractValue rdr)
let GetSqlConnection (conName : string) =
let conStr = ConfigHandler.GetConnectionString conName
try
let con = new SqlConnection(conStr)
con.Open()
Some(con)
with
| :? System.Exception as ex -> printfn "Failed to connect to DB %s with Error %s " conName ex.Message; None
| _ -> printfn "Failed to connect to DB %s" conName; None
let GetSqlCommand (spName : string) (con : SqlConnection) =
let cmd = new SqlCommand()
cmd.Connection <- con
cmd.CommandText <- spName
cmd.CommandType <- CommandType.StoredProcedure
Some(cmd)
let AddParameters (cmd : SqlCommand) (paramList : SqlParameter list) =
paramList |> List.iter (fun p -> cmd.Parameters.Add p |> ignore)
let ExecuteReader (cmd : SqlCommand ) =
try
Some(cmd.ExecuteReader())
with
| :? System.Exception as ex -> printfn "Failed to execute reader with error %s" ex.Message; None
このコードには複数の問題があります
何よりもまず、 Option.bind を繰り返し使用すると非常にイライラします...そしてノイズが追加されます。出力が None であるかどうかを確認し、そうでない場合は続行するためのより明確な方法が必要です。
最後に、リーダー、コマンド、および接続を閉じて破棄できるクリーンアップ関数が必要です。しかし、現在、パイプラインの最後にあるのはリーダーだけです。
パラメータを追加している関数...戻り値の型が送信されたコマンドと同じであるため、コマンドパラメータの「状態」を変更しているように見えます...いくつかの状態が追加されています。より経験豊富な関数型プログラマーがこれをどのように行ったのだろうか。
Visual Studio は、例外処理を行う各場所で警告を表示します。それの何が問題なのですか」と言う
このタイプのテストまたはダウンキャストは常に保持されます
このコードの外観は次のとおりです
let x : MyRecord seq = GetConnection "con" |> GetCommand "cmd" |> AddParameter "@name" SqlDbType.NVarchar 50 |> AddParameter "@policyname" SqlDbType.NVarchar 50 |> ExecuteReader |> FunctionToReadAndGenerateSeq |> CleanEverything
コードを目的のレベルにする方法と、その他の改善点をお勧めできますか?