Linq with inheritable Dao

Linq to SQLでDAOパターンかつCRUDな感じにしたくてInterfaceとかabstractでいろいろやっていたのだが、ジェネリックでシンプルに解決できそうなのでメモ。


DBの後始末等いろいろ雑なのはご愛嬌。


ポイントは

    public class BaseDao : IDisposable {

        protected MyDatabase ctx;

        public BaseDao() {
            this.ctx = new MyDatabase(Resources.ConnectionString);
        }

        public T Find<T>(T entity) where T : class {
            <del>try {</del>
                return (from o in this.ctx.GetTable<T>() where o == entity select o).Single<T>();
            <del>} catch (Exception e) {
                throw e;
            }</del>
        }

        public IEnumerable<T> FindAll<T>() where T : class {
            try {
                return from o in this.ctx.GetTable<T>() select o;
            } catch (Exception e) {
                throw e;
            }
        }

        public void Put<T>(T entity) where T : class {
            try {
                this.ctx.GetTable<T>().InsertOnSubmit(entity);
                this.ctx.SubmitChanges();
            } catch (Exception e) {
                throw e;
            }
        }

        public void Delete<T>(T entity) where T : class {
            try {
                this.ctx.GetTable<T>().DeleteOnSubmit(entity);
                this.ctx.SubmitChanges();
            } catch (Exception e) {
                throw e;
            }
        }

        #region IDisposable Members

        public MyDatabase GetContext() {
            return this.ctx;
        }

        public void Dispose() {
            this.ctx.Dispose();
        }

        #endregion
    }


あ、Updateがねぇや。まぁ、あとはこれを継承して使うと。


C#の情報って@○T(伏字)とかばっかで古いのしか見つからないんだけど、みんなどうしてんの??


今回参考にしたのはこちら。
http://blogs.msdn.com/b/msmossyblog/archive/2009/01/11/linq-to-sql-poormans-dao-crud.aspx


【2010/12/05 追記】
例外処理が仕方が間違っている。
Findについてはクエリをreturnしているだけなので、この時点では評価は行われていませんと。
これを実際にforeachなどするときに例外処理すべし。


参考にさせていただきました。
http://d.hatena.ne.jp/gsf_zero1/20091204/p3

eclipseでlift

やっぱりIDE使った方が学習効率がいってもんで、
eclipseにliftプロジェクトを作成してみます。


プロジェクトの作成まではこちら。
http://d.hatena.ne.jp/ktdk/20100507


作成したらディレクトリの中に入って、

mvn eclipse:eclipse


これでeclipseに必要なファイルとか作成されます。


eclipseを起動して、Scalaプラグインを入れましょう。


URL:http://www.scala-lang.org/scala-eclipse-plugin



プラグインのインストールが完了したら、
[ファイル]>[インポート]>[一般]>[既存プロジェクトをワークスペースへ]で
該当するプロジェクトをインポートします。



次にコマンドラインから以下を実行。

mvn -Declipse.workspace="[ワークスペースのディレクトリ名]" eclipse:add-maven-repo


あと、プロジェクトのプロパティからJavaのビルドパスを開いて、
変数にM2_REPOを追加する。(%USER%はユーザー名ディレクトリ)

M2_REPO = %USER%\.m2\repository


んで[実行]>[実行の構成]>[Scalaアプリケーション]に新規構成を追加し、


プロジェクト名:helloworld (例)
メインクラス:RunWebApp


と入力して実行。


Jettyが正常に起動すればOKです。


lift入門

scalaをいじってみたけど、実際に何か作ってみないとよくわからんので、
Twitterfoursquareも使っているというliftに入門してみた。

liftとは


めんどいので飛ばします


http://codezine.jp/article/detail/4310?p=2

環境


java, scala, maven のインストールは各サイト参照

プロジェクトの作成


ここからが本番です。以下を実行。

mvn archetype:generate -U \
-DarchetypeGroupId=net.liftweb \
-DarchetypeArtifactId=lift-archetype-basic \
-DarchetypeVersion=1.1-M8 \
-DarchetypeRepository=http://scala-tools.org/repo-releases \
-DremoteRepositories=http://scala-tools.org/repo-releases \
-DgroupId=demo.helloworld \
-DartifactId=helloworld \
-Dversion=1.0


archetype:create とご説明している方もいらっしゃいますが、現在は generate になっているみたい。
DarchetypeVersion は1.0だとサーバー起動後にアクセスエラーになりました。(scalaのバージョンが悪かったのかな?)


【2010/05/17 追記 >>】
http://scala-tools.org/repo-releases/net/liftweb に、
Archetypeごとのリポジトリがあるので、バージョンを随時チェック。
現時点の最新は 2.0-M5。
【<< 2010/05/17 追記】


んで

cd helloworld

mvn jetty:run

...

[INFO] Started Jetty Server
[INFO] Starting scanner at interval of 5 seconds.


と実行して、http://localhost:8080/ にアクセスすると以下の画面が表示されます。
(初回起動時は結構時間がかかります)



起動ポートを変えたい場合は、

mvn jetty:run -Djetty.port=80


ってやればおk。


基本的な導入自体はすごく簡単だけど、やっぱり気をつけなくちゃいけないのが、
言語とフレームワークのバージョン。rails もなんか怪しいときあったし。


もっと実例が増えることに期待。

Apache2上でRailsアプリケーションを動かす

Phusion Passenger(mod_rails for Apache)を利用します。

まず、passengerをインストール

gem install passenger

Apacheモジュールのビルドとインストール

passenger-install-apache2-module

インストール完了後にhttpd.confの設定が表示されるので、
それに従いhttpd.confに追記。

LoadModule passenger_module /usr/local/lib/ruby/gems/1.9.1/gems/passenger-2.2.11/ext/apache2/mod_passenger.so
PassengerRoot /usr/local/lib/ruby/gems/1.9.1/gems/passenger-2.2.11
PassengerRuby /usr/local/bin/ruby

VirtualHostも設定。

<VirtualHost *:80>
  ServerName www.example.com
  DocumentRoot /var/www/sample/public
  <Directory /var/www/sample/public>
    AllowOverride all
    Options -MultiViews
    RailsEnv development # railsをdevelopmentモードで起動する場合
  </Directory>
</VirtualHost>

以上でhttpd.confの設定は終了。Apacheを再起動。

httpd.confで設定しているディレクトリ(ここでは/var/www/)に移動して

rails sample

Railsアプリケーション作成。さらに

rake db:create

でデータベースを作成。

http://www.example.com/ にアクセスして以下の画面が表示されることを確認。

About your application’s environment のとこをクリックして、以下が表示されることを確認。

この表示が We’re sorry, but something went wrong.
になってしまうことがありますが、データベースを再起動したりすると正しく表示されました。(原因不明)

Apacheでバーチャルホスト

ホスティングサービスみたいに aaa.example.com, bbb.example.com
複数ドメインがあるっぽく運用する設定例。IPアドレスはひとつ。


まず、DNSのCNAMEに *.example.comワイルドカードで登録しておく。

んで、/etc/httpd/conf/httpd.conf に

#
# Load config files from the config directory "/etc/httpd/conf.d".
#
Include conf.d/*.conf

ってあれば、/etc/httpd/conf.d/ に virtualhost.conf とか拡張子が.confの適当なファイルを作成して以下を記述。
なければhttpd.conに直接記述するか、Include conf.d/*.confを記述すればいいのかな?

NameVirtualHost *:80

# メイン
<VirtualHost *:80>
  ServerName www.example.com
  DocumentRoot /var/www/html
</VirtualHost>

<VirtualHost *:80>
  ServerName aaa.example.com
  DocumentRoot /home/aaa/public_html
  ScriptAlias /cgi-bin/ "/home/aaa/public_html/cgi-bin/" # CGIを動かす場合
</VirtualHost>

設定ファイルを再読み込み。

/etc/rc.d/init.d/httpd reload

アクセス確認は、クライアントのhostsファイルに

192.168.0.2	www.example.com
192.168.0.2	aaa.example.com

と書いてブラウザからアクセス。DocumentRootにはhttpd.confのDirectoryIndexに指定してあるファイル(index.htmlなど)を置いておこう。

DiCEのIP更新がうまくいかない

VirtualHostとかChroot設定しているときに、いつの間にか外部からアクセスできなくなった。

この設定が関係あるわけもないので、基本的なところからチェック。

...DNSグローバルIPが違うじゃないかorz

グローバルIPの調べ方 on Linux

wget -q -O - ipcheck.ieserver.net

DiCEで更新かけてみたがうまく変わらないので、以下を拝借しました。(EveryDNS用)
グローバルIP取得の部分がうまく動かなかったので、上記のものと差し替え。
/cron/ip_update.sh とかで適当に保存。
あと、現在DNSに登録されているIPを/tmp/oldip.everydnsに記述しておく。

#!/bin/bash
hostname="example.com"
USER="username"
PASS="password"
VER="0.1"

#IP=$(curl -s http://myip.dk/ | egrep -m1 -o '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')
IP=$(wget -q -O - ipcheck.ieserver.net)
if [ -r "/tmp/oldip.everydns" ]; then
  OLDIP=`cat /tmp/oldip.everydns`
  if [ "$OLDIP" = "$IP" ]; then
        exit 0
  else
        RETURN=$(curl -s http://${USER}:${PASS}@dyn.everydns.net/index.php?ver=${VER}&ip=${IP}&domain=${hostname})
        echo $RETURN | grep "IP change suceeded" > /dev/null 2>&1
        if [ "$?" -eq "0" ]; then
              echo $IP > /tmp/oldip.everydns
        else
              echo "" > /tmp/oldip.everydns
        fi
  fi
fi

これを定期実行するためcronに設定。
エディタを開いて記述。

# crontab -e

* * 7 * * /cron/ip_update.sh

ちなみにcronの書き方は、左から

minute 0〜59
hour 0〜23
day_of_month 0〜31
month 1〜12 または jan〜dec
day_of_week 曜日 0〜6 または sun〜sat
command コマンド行  

【2010/03/21 追記】
DiCEのsetupでプライベートIPアドレスを検出対象からはずすとうまく更新されるようになりました。