おはよう君需要なし

求不得苦な日々

ASP.net MVCでコンテキストを別プロジェクトに分離する

はじめに

Web(MVCなアプリケーション)で使用するデータベースを他のプロジェクトからいじれると便利なことが多いです。コンソールからデータベースを参照するときなど。

そういう時ってWebアプリケーションの本体を参照して紐付けてしまうと大変なことになってしまうので、モデルは別プロジェクト(クラスライブラリ)として独立させた方が便利なはずです。で、モデルを分離するならデータベースにアクセスする部分(DbContext)もクラスライブラリとして独立させてしまうべきだろうというのが動機です。

こんな感じ

Entity Framework 6のCode first前提です。

 構成

プロジェクトの構成はこのような感じで。

─┬─Application.Web
 │  …Webアプリケーション本体
 │
 ├─Application.DataAdapter 
 │  …データベースアクセスクラス
 │
 ├─Application.Entity
 │  …データベースのモデル
 │
 ├─Application.ConsoleClient
 │  …コンソールアプリケーション(管理プログラムなど)
 │
 └─Application.TestProgram
    …ちょっとしたテストを書くプロジェクト

注意点

特になし。プロジェクトの参照設定をきちんと設定できれば特に問題になる部分はないかと。

マイグレーションで困った!

で、まぁ順調に実装していたわけなんですが何だかマイグレーションの調子がよろしくない。

データベースの作成後、'xxxxx' コンテキストの背後にあるモデルが変更されました。
Code First Migrations を使用したデータベースの更新を検討してください
 (http://go.microsoft.com/fwlink/?LinkId=238269)。

というエラー。リンク先に書いてあるマイグレーションの手順は全部試してみたんだがなぁ・・・

解決

というわけで四苦八苦していたわけなんですが、なんともマヌケなことで、プロジェクトを分離したせいで マイグレーションツールがコンテキストのクラスを見失っていたのが問題みたいです。

blog.qaramell.com

データ ポイント - 複数モデルを対象とする EF6 Code First Migrations

このサイトに書いてあるとおりに、分離したコンテキストにそれぞれマイグレーションの設定をしてあげることで、うまくマイグレーションできるようになりましたとさ。トホホ。

おわりに

うむ。スッキリした。

JSONでこういう書き方

 [
    {
        "name" : "task1",
        "params" : {
            "param1_task1" : 1,
            "param2_task1" : 2,
            "param3_task1" : 3
        }
    },
    {
        "name" : "task2",
        "params" : {
            "param1_task2" : 1,
            "param2_task2" : 2
        }
    },
    {
        "name" : "task_end",
        "params" : {
            "param1_task3" : "hogehgoe",
            "param2_task3" : [1,2,3,4]
        }
    }
]

HTTPでjsonのstringを受け取ってサーバー側でパースしてタスクを実行するっていうプログラムを書いているんですが、タスクごとに異なったパラメータを与えたいという問題に対してどうアプローチするかってのがよくわかりません・・・

各タスクが取るパラメータは、それぞれ異なっていて、名前も違えば型も違う。そういう状況にはどう対処すべきなんでしょうか。

解決策(とりあえず)

1つ考えてみた方法としては、jsonをパースするにはするんですが、それをいきなりクラスに変換して持つのではなく、シリアライズしてStringで持っておいてタスク実行時に再度パースするというやり方。ぜんぜんスマートじゃない。

class Param {
    [JsonProperty("name")]
    public string Name { get; set; }

    [JsonProperty("params")]
    public JObject Parameters { get; set; }

    public string ParamString { get; set; }
}


// 略

var result = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Param>>(strParam);

if (result[i].Name == "task1")
{
var tmp = result[i].Parameters.ToObject<ParamTask1>();
result[i].ParamString = JsonConvert.SerializeObject(tmp);
}

// 略

みたいな。ParametersParamStringという2つの変数で重複しているのでなんだかクソ無駄な気がしますが。

あれ?

???「JObjectで持っておいて、都度`ToObject`するんじゃダメなのか?」

あれれ?何か難しく考えすぎてたっぽい?

あほでした(完)