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。(它似乎只支持简单的聚合方法,例如.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

如果你真的只想实现mentionend 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”的更改是有意义的,具体取决于您拥有的语言环境键和您要求的异国情调,但我现在能想到的唯一例子 :) 请求“ch”时,“fr-ch”可能会给您法语(suisse德语)

于 2012-09-03T15:33:09.247 回答