2

H!

SQLデータベース上でNHibernateを使用するWebアプリケーションのロケールフォールバックを使用してメッセージストアをコーディングしています。たとえば、の結果はstore.Get("Greet", "fr-ca-on")、このデータ(fr-ca)からの最適な値になります。

Key    Locale    Message
-----  ------    --------
Greet            Hello
Greet  fr        Bonjour!
Greet  fr-ca     Âllo!
Greet  fr-ca-qc  Âllo toi!

フォールバックを実装するために、このようなさまざまなクエリを試しました。

string[] locales = new[] { "fr-ca-on", "fr-ca", "fr", "" }; 
return (
   from Translation translation in reader.Get<Translation>()
   where locales.Contains(translation.Locale)
   group translation by translation.Key into translationGroup
   select translationGroup.OrderByDescending(p => p.Locale.Length).First()
   //or: select translationGroup.MaxBy(p => p.Locale.Length)
);

これらはメモリ内で非常にうまく機能しますが、NHibernateはグループ選択をSQLに変換できません。(selectではなく、のような単純な集計メソッドのみをサポートしているよう.Count()です。)

NHibernateがクエリをSQLに変換できるように、このクエリを書き直すにはどうすればよいですか?クエリをメモリに早めに延期しない方法は考えられません。これは、アプリケーションのパフォーマンスを実際に損なうことになります。

(翻訳に関連する他のエンティティがあるため、リソースファイルは使用しません。)

4

2 に答える 2

1

私はそれをLINQサブクエリとして書き直すことができました:

string[] locales = new[] { "fr-ca-on", "fr-ca", "fr", "" }; 
return (
    from Translation translation in reader.Get<Translation>()
    where
        locales.Contains(translation.Locale)
        && (translation.Locale.Length == reader
            .Get<Translation>()
            .Where(p => locales.Contains(p.Locale) && p.Key == translation.Key)
            .Max(p => p.Locale.Length)
        )
    select translation
);

NHibernateはサブクエリを適切に処理し、それを次の(プリティファイされた)SQLに変換します。

SELECT *
FROM [translation] translation
WHERE
    [locale] IN ('fr-ca-on', 'fr-ca', 'fr', '')
    AND LEN([locale]) = (
        SELECT CAST(MAX(LEN(sub.[locale])) AS INT)
        FROM [translation] sub
        WHERE
           sub.[locale] IN ('fr-ca-on', 'fr-ca', 'fr', '')
           AND sub.[key] = translation.[key]
)
于 2012-09-03T21:12:01.907 に答える
0

あなたが本当に言及を実装したいだけならGetメソッド

どのようにそのことについて?

private string Get(string key, string locale)
{
    return (from Translation t in reader
       where t.Key == key && (t.Locale == null || t.Locale == "" || locale.StartsWith(t.Locale))
       orderby t.Locale descending
       select t.Value).First();
}

PS:「StartsWith」への変更は、使用しているロケールキーとエキゾチックなリクエストに応じて意味がありますが、今考えられる唯一の例です:)「fr-ch」は「ch」をリクエストするときにフランス語を表示する場合があります(スイスドイツ人)

于 2012-09-03T15:33:09.247 に答える