私は単純な User エンティティを持っています:
public class User
{
public virtual int Id { get; set; }
public virtual DateTime CreationDate { get; set; }
public virtual DateTime ModifiedDate { get; set; }
public virtual string Email { get; set; }
public virtual string Name { get; set; }
public virtual IList<Phone> Phones { get; set; }
}
public class Phone
{
public virtual string CountryCode { get; set; }
public virtual string Code { get; set; }
public virtual string Number { get; set; }
public virtual string Comment { get; set; }
}
私のマッピングは次のように定義されています:
public class UserMap : ClassMap<User>
{
public UserMap ()
{
this.Table ("Users");
this.Id (x => x.Id).CustomSqlType ("bigint").GeneratedBy.HiLo ("1000");
this.Map (x => x.CreationDate);
this.Map (x => x.ModifiedDate).Column ("LastUpdatedDate");
this.Map (x => x.Email).Length (255).Not.Nullable ().Unique ();
this.Map (x => x.Name).Column ("UserName").Length (255);
this.HasMany (x => x.Phones).Inverse ();
}
}
public class PhoneMap : ClassMap<Phone>
{
public PhoneMap ()
{
this.Table ("Phones");
this.Id ().GeneratedBy.Identity ();
this.Map (x => x.CountryCode).Length (5);
this.Map (x => x.Code).Length (10);
this.Map (x => x.Number).Length (50).Not.Nullable ();
this.Map (x => x.Comment).Length (255);
}
}
追加の規則は次のとおりです。
PrimaryKey.Name.Is (x => "Id"),
ForeignKey.EndsWith ("Id"),
DefaultAccess.Property (),
DefaultCascade.All ()
電話番号があり、名前が「A」で始まる上位 100 人のユーザーを選択する必要があります。しかし、電話を含むユーザー オブジェクトを読み込む必要があります。
だから私はこのクエリを行います:
var users =
(
from user in session.Query<User> ()
where
user.Name.StartsWith ("a")
&&
user.Phones.Any ()
select user
)
.Fetch (x => x.Phones)
.Take (100)
.ToArray ();
そして、72人のユーザーしか獲得できませんでした。
なんで?NHibernate は左外部結合を使用して単一の TOP N 選択を生成し、SQL は同じユーザー エンティティに対して複数のレコードを返すためです。これは、一部のユーザーが複数の電話を持っているためです。しかし、それはすべて TOP N に対してカウントされるため、電話に参加しているユーザーの 100 のレコードを取得しますが、一意のエンティティはそのうちの 72 のみです。
それを行う適切な方法はありますか?