C#+asp.netでアプリケーションを作ろうと思う。
で、今回フレームワークとしてVici MVCを見つけた。けっこう使いやすそう。
そして、DBアクセスにはvici coolstorageを使おう!
これまた、結構使いやすそう。
ところが、ちょっと壁にぶつかった。
というのも、データベースにはすでにデータが有る。というか初期状態のデータがすでにある。
そして、主キーはPrimaryと指定してあるが、前に作っていたプログラムでは新規レコード追加時にコードで次のキー値をセットしていた。
そして、そのキー値が別のリレーションを貼ったテーブルにも使われていた。
つまり、このフィールドは自動的にインクリメントしたいけど、いま入っている値はそのまま利用したい。
単純にコーディングすると、モデルクラスのイベント処理で対応できるらしい。
http://vici.stackexchange.com/questions/94/custom-primary-key-in-coolstorage
ところが、モデルがいっぱいあって、全部のクラスに同じコードを書くのが面倒だし、バグの元になる。
訂正が必要になったときに見落とす可能性が増えるからね。
いろいろ調べながらクラスを作ってみた。
やっぱりGenericはすごいね。今日もまた感動した。
まず、すべてのテーブルはIDという整数値のフィールドがあって、そこが主キーになっている。
なので、それをインターフェイスとして宣言する。
public interface M_IDTable
{
int ID { get; set; }
}
よし。
次にGenericを利用してIDフィールドの最大値+1を取ってくるメソッドを作ろう。
public class MaxIdentifierUtil
{
public static int GetNext<T>() where T : CSObject<T, int>
{
int? MaxId = (int?)CSObject<T>.GetScalar("ID", CSAggregate.Max);
if (MaxId == null)
{
return 1;
}
return (int)MaxId + 1;
}
public static void SetNextMaxID<T>(T sender, EventArgs e) where T : CSObject<T, int>, M_IDTable
{
sender.ID = MaxIdentifierUtil.GetNext<T>();
}
}
次に、モデルクラス。これはCSObjectを継承しなければいけない。さらに、今回作ったM_IDTableインターフェイスも実装する。
で、追加イベントで上記クラスのSetNextMaxIDメソッドを呼び出すようにする。
[MapTo("M_UserLevel")]
public abstract partial class M_UserLevel : CSObject<M_UserLevel, int>, M_IDTable
{
static M_UserLevel(){
AnyObjectCreating += MaxIdentifierUtil.SetNextMaxID<M_UserLevel>;
}
public abstract int ID { get; set; } // Primery Key
public abstract string Name { get;set;}
}
動いた!!
ありがとうGeneric!
コメントをお書きください