[英]QueryOver multiple tables with NHibernate
I'm trying to left join multiple tables and project some columns that result from this join onto a new entity, and then taking a few records from this result from my database. 我试图离开联接多个表,并将由此联接产生的一些列投影到新实体上,然后从数据库中获得该结果的一些记录。 I've taken a look on a few similar questions here on SF, but I'm not managing to assemble all of those parts into a piece of code that works.
在SF上,我已经研究了一些类似的问题,但是我没有设法将所有这些部分组合成有效的代码。
Here is the query I'm trying to generate with NHibernate: 这是我尝试使用NHibernate生成的查询:
select * from
( select LOC_Key.KeyName, LOC_Translation.TranslationString, LOC_Translation.Comments
from LOC_Key
left join LOC_Translation
on LOC_Key.ID = LOC_Translation.KeyID and LOC_Translation.LanguageID = 6
order by LOC_Key.KeyName
) as keyTable
limit 0,100
I have three entities here, Key, Translation and Language. 我在这里有三个实体,即键,翻译和语言。 A Key is a unique string identifier for different translations of a same word in different languages.
关键字是一个唯一的字符串标识符,用于同一单词在不同语言中的不同翻译。 I want to show the first n keys in alphabetical order for a language, but I want all keys listed, not only the ones that are translated (that's why I'm using a left join).
我想按字母顺序显示一种语言的前n个键,但我希望列出所有键,而不仅仅是已翻译的键(这就是为什么我使用左联接)。
I took a look at QueryOver<>
, Select()
method and List<object[]>()
method but I can't even manage to have a code that compiles in the first place. 我看了一下
QueryOver<>
, Select()
方法和List<object[]>()
方法,但是我什至无法管理要首先编译的代码。
I could use C# linq after getting all records from the tables Key and Translation, having something like this: 从表Key和Translation获得所有记录后,我可以使用C#linq,如下所示:
IEnumerable<string> k = RepositoryKey.GetLimits( offset, size ).Select( x => x.KeyName );
IEnumerable<TranslationDescriptor> t = RepositoryTranslation.GetAllWhere( x => x.LanguageID.LanguageCode == language && k.Contains ( x.KeyID.KeyName ) ).ToList().ConvertAll( new Converter<Translation, TranslationDescriptor>( ( x ) => { return new TranslationDescriptor { LanguageCode = x.LanguageID.LanguageCode, KeyName = x.KeyID.KeyName, Comments = x.Comments, TranslationString = x.TranslationString }; } ) );
var q = from key in k
join trl in t on key equals trl.KeyName into temp
from tr in temp.DefaultIfEmpty()
select new TranslationDescriptor { KeyName = key, LanguageCode = language, Comments = ( tr == null ) ? string.Empty : tr.Comments, TranslationString = ( tr == null ) ? string.Empty : tr.TranslationString };
However, that's very slow. 但是,这非常慢。 By the way, my implementation for GetLimits and GetAllWhere is:
顺便说一下,我对GetLimits和GetAllWhere的实现是:
public IEnumerable<T> GetAllWhere(Func<T, bool> func)
{
var products = Session.Query<T>().Where(func);
return products;
}
public IEnumerable<T> GetLimits(int offset, int size)
{
return Session.CreateCriteria(typeof(T)).SetFirstResult(offset).SetMaxResults(size).List<T>();
}
Thank you for your help! 谢谢您的帮助!
Bruno 布鲁诺
I'm guessing a little bit at your entities and mappings, but the following might help you get ideas. 我在猜测您的实体和映射,但以下内容可能会帮助您获得想法。 It joins
Key
to Translation
with a left outer join, then projects the results to a new DTO object. 它使用左外部连接将“
Translation
Key
连接起来,然后将结果投影到新的DTO对象。
[Test]
public void LeftOuterProjection()
{
using (var s = OpenSession())
using (var t = s.BeginTransaction())
{
// Set up aliases to use in the queryover.
KeyDTO dtoAlias = null;
Key keyAlias = null;
Translation translationAlias = null;
var results = s.QueryOver<Key>(() => keyAlias)
.JoinAlias(k => k.Translations, () => translationAlias, JoinType.LeftOuterJoin)
.Where(() => translationAlias.LanguageId == 6)
.OrderBy(() => keyAlias.KeyName).Asc
.Select(Projections.Property(() => keyAlias.KeyName).WithAlias(() => dtoAlias.KeyName),
Projections.Property(() => translationAlias.TranslationString).WithAlias(() => dtoAlias.TranslationString),
Projections.Property(() => translationAlias.Comments).WithAlias(() => dtoAlias.Comments))
.TransformUsing(Transformers.AliasToBean<KeyDTO>())
.List<KeyDTO>();
}
}
public class KeyDTO
{
public string KeyName { get; set; }
public string TranslationString { get; set; }
public string Comments { get; set; }
}
public class Key
{
public int Id { get; set; }
public string KeyName { get; set; }
public IList<Translation> Translations { get; set; }
}
public class Translation
{
public Key Key { get; set; }
public int LanguageId { get; set; }
public string TranslationString { get; set; }
public string Comments { get; set; }
}
The modifications I made to my code following ngm suggestion (thanks!): 我根据ngm建议对代码进行的修改(谢谢!):
Language l = RepositoryLanguage.GetSingleOrDefault(x => x.LanguageCode
== language);
KeyTranslationDTO dtoAlias = null;
Key keyAlias = null;
Translation translationAlias = null;
var results = RepositoryKey.GetSession()
.QueryOver<Key>(() => keyAlias)
.OrderBy(() => keyAlias.KeyName).Asc
.JoinQueryOver<Translation>( k => k.Translations, () => translationAlias, JoinType.LeftOuterJoin, Restrictions.Where( () => translationAlias.LanguageID == l ) )
.Select(Projections.Property(() => keyAlias.KeyName).WithAlias(() => dtoAlias.KeyName),
Projections.Property(() => translationAlias.TranslationString).WithAlias(() => dtoAlias.TranslationString),
Projections.Property(() => translationAlias.Comments).WithAlias(() => dtoAlias.Comments))
.TransformUsing(Transformers.AliasToBean<KeyTranslationDTO>())
.Skip(index).Take(amount)
.List<KeyTranslationDTO>();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.