4

1 対 1 の関係を持つ 2 つの NHibernate エンティティがあります。彼らを犬と飼い主と呼びましょう。

public class Dog 
{
    public virtual int Id { get;set; }
    public virtual Owner Owner { get; set; }
}

public class Owner 
{
    public virtual int Id { get; set; }
    public virtual Dog Dog { get; set; }
}

また、Dog には所有者が 1 人または 0 人いる場合があります。Fluent/NHibernate のマッピングは次のとおりです。

public class DogMap : ClassMap<Dog> 
{
    public DogMap() 
    {
        Table("Dogs");

        Id(x => x.Id);

        HasOne( x=> x.Owner)
            .Fetch.Join()
            .Not.LazyLoad();
    }
}

public class OwnerMap : ClassMap<Owner> 
{
    public OwnerMap() 
    {
        Table("Owners");

        // Owners share the same primary-key as dogs
        Id(x => x.Id).GeneratedBy.Foreign("Dog"); 

        References( x => x.Dog)
            .Unique()
            .Not.LazyLoad();
   }
}

ここで、 Owner を持たない Dogsを選択したいだけです。

クエリは次のようになると想定しました。

Owner owner = null;
var ownerlessDogs = session
    .QueryOver<Dog>()
    .Left.JoinAlias(x => x.Owner, () => owner)
    // Restrict on alias
    .WhereRestrictionOn(() => owner).IsNull
    .List();

しかし、ご想像のとおり、これは機能しません。「オブジェクト参照が...に設定されていません」がスローされます。

私が試してみると、

var ownerlessDogs = session
    .QueryOver<Dog>()
    .Left.JoinAlias(x => x.Owner, () => owner)
    // Restrict on property of root object
    .WhereRestrictionOn(x => x.Owner).IsNull
    .List();

それは基本的に生成します

SELECT {{relevant columns}}
FROM Dogs dogs
LEFT OUTER JOIN OWNERS owners
WHERE dogs.Id IS NULL

ほとんど正しいですが、所有者の犬の外部キーではなく、犬の主キーでフィルタリングしています。

4

1 に答える 1

4

Hibernateフォーラムの古い投稿の助けを借りて、解決策を見つけました。

public class DogMap : ClassMap<Dog> {

    public DogMap() {
        Table("Dogs");
        Id(x => x.Id);

        HasOne( x=> x.Owner)
          .Fetch.Join();
    }
}

public class OwnerMap : ClassMap<Owner> {

   public OwnerMap() {

   Table("Owners");

   //owners share the same primary-key as dogs
   Id(x => x.Id).GeneratedBy.Foreign("Dog"); 

   //both sides should be mapped as HasOne
   HasOne( x => x.Dog)
     .Constrained()
     .Fetch.Join();
   }
}

そして、作業クエリは

var ownerlessDogs = session
  .QueryOver<Dog>()
  .Left.JoinAlias(x => x.Owner, () => owner)
  //this is the trick, restrict on Id
  .WhereRestrictionOn( x => x.Owner.Id ).IsNull
  .List();
于 2013-03-04T06:40:50.917 に答える