8

C#/。Netの世界には、透過キャッシュを含むNHibernateやActiveRecordなどのORMがあります。データベースの更新は透過的にキャッシュに複製され、オブジェクトは利用可能な場合はキャッシュから直接取得されます(多くの場合memcachedを使用)。

透過的なキャッシュがDBIx::Classを使用するPerlで利用できるようには見えません。私は何か見落としてますか?それは一般的なニーズのようですが、CPANやGoogleで何も見つからなかったのには驚いています。

4

4 に答える 4

6

半透過的に DBIx::Class::Cursor::Cached (DBIC のような mst から) があります。ただし、接続またはスキーマ オブジェクトに Cache オブジェクトを提供する必要があります。残念ながら、非常に文書化されていないようです。

クックブックには、DBIC で Tie::Cache を使用する例があり、DBIx::Class::ResultSet で (get|set|clear)_cache 関数もありますが、おそらく必要なものではないでしょう。

于 2009-08-12T19:04:45.077 に答える
5

CHIでキャッシングを追加する簡単な方法を次に示します。私は実際にこれを試していないので、特に DBIC 結果セットのシリアル化に関して、私が考慮していない落とし穴があるかもしれません。

package My::Table;
use strict; 
use warnings;

use base 'DBIx::Class';

use Storable 'freeze';
use CHI;

$Storable::canonical = 1;

__PACKAGE__->load_components(qw/Core/);
__PACKAGE__->table('mytable');

# ....

my $CACHE = CHI->new( driver => 'Memory' );

sub search { 
    my $self = shift;

    my $key = freeze( \@_ );      # make cache key from params
    if ( my $rs = $CACHE->get( $key ) ) { 
        return $rs;
    }

    # Note: there are issues with context propagation here
    my $rs = $self->next::method( @_ );
    $CACHE->set( $key => $rs );
    return $rs;
}

sub update { 
    my $self = shift;

    my @keys = $self->find_all_cache_items_affected_by_this_update( @_ );
    $CACHE->remove( $_ ) for @keys;

    $self->next::method( @_ );
}

少し不格好ですが、良い出発点だと思います。すべての DBIx::Class テーブル クラスの基底クラスでこの種のことを行う場合、透過的なキャッシングを非常に簡単に構築できるはずです。

于 2009-08-12T19:30:55.880 に答える
1

私はDBIx::Classベースのモデルでこれと同じニーズに遭遇しました。ここで回答を確認した後、私が探しているソリューションであるものは実際には見つかりません。この問題に苦労した後、私は自分のビジネスレイヤーがキャッシュを処理する必要があると考え始めているので、DBIx::Classをビジネスロジックを実装しない永続レイヤーとして扱います。

たとえば、理想的なキャッシュを使用した現在のコードは次のようになります。

my $network = SL::Model::App->resultset('Network')->search({ ip => '127.0.0.1' });

また、$ networkオブジェクトは、DBIx::Classスキーマの初期化中に構成した$memcachedキャッシュから提供されます。

新しいコードは次のようになります。

my $network = SL::Network->find_by_ip_or_create({ ip => '127.0.0.1' });

一方、近くのモジュールでは:

package SL::Network;
...
use SL::Model::App;
use SL::Cache;

our $cache = SL::Cache->new;

sub find_by_ip_or_create {
    my ($class, $args) = @_;

    my $network;
    unless ($network = $cache->get('network|' . $args->{ip}) {
        $network = SL::Model::App->resultset('Network')->find_or_create({ wan_ip => $args->{ip}});
        $cache->set('network|' . $args->{ip} => DBIx::Class::Schema->freeze($network));
    }
    return $network;

}

あなたはその考えを理解します。

于 2010-11-05T06:13:53.903 に答える
0

に「検索」メソッドを追加する代わりに、それを追加したいと思いますMy::Table

DBIx::Class::ResultSet次のように、によって提供される ->search メソッドを拡張することもできます。

package Schema::ResultSet::My::Table;
use base 'DBIx::Class::ResultSet';

sub search {
    my ( $self, $args ) = ( shift, shift );

    # do what you want here with the args passed to ->search
    return $self->next::method( $args, @_ );
}

また、ResultSet をサブクラス化できる可能性が非常に高いため、この変更された ( cached ) 検索をすべての ResultSet に提供できるため、キャッシュ コードをすべてのテーブルの 1 か所に保持できます。

ただし、これはまだテストしていません。

上記の例を機能させるには、スキーマ クラスの名前のファイルをディレクトリ"../Schema/ResultSet/"に配置し、Schema.pm に含まれていることを確認します。"load_namespaces();"これにより、そこに配置したオーバーロードされたすべてのクラスが適切に自動ロードされます ( Catalyst のインストールは自動的にそれを行いましたが、覚えていません)。

DBIx::Class::ResultSet

于 2014-10-31T21:18:37.807 に答える