23

Task クラスをロードするたびに、db にデータがあるにもかかわらず、Document プロパティは常に null です。

タスク クラス:

public class Task
{
    public virtual Document Document { get; set; }

AutoPersistenceModel のタスク マッピングのオーバーライド:

public void Override(AutoMap<Task> mapping)
{
    mapping.HasOne(x => x.Document)
        .WithForeignKey("Task_Id");

NHProf が実行されていると言っていることがわかるように、結合条件が間違っているため、WithForeignKey が有効にならないようです。実際、上記のコードには任意の文字列を記述できますが、違いはありません。

FROM   [Task] this_
    left outer join [Document] document2_
    on this_.Id = document2_.Id

そのはず:

FROM   [Task] this_
    left outer join [Document] document2_
    on this_.Id = document2_.Task_Id

IDが一致するようにデータベース内のデータをハックすると、データがロードされますが、明らかにこれは正しくありません-しかし、少なくともデータをロードすることを証明します。

編集:流暢な nhib ソースを調べて XML を見つけると、次のようになります。

<one-to-one foreign-key="Task_Id" cascade="all" name="Document" class="MyProject.Document, MyProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> 

編集:スキーマは次のとおりです。

CREATE TABLE [dbo].[Document](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Task_Id] [int] NOT NULL,

CREATE TABLE [dbo].[Task](
[Id] [int] IDENTITY(1,1) NOT NULL,

誰でもアイデアはありますか?

ありがとう

アンドリュー

4

6 に答える 6

94

今日も同じ問題に遭遇しました。トリックは、 .ForeignKey(...) を .HasOne マッピングで使用するのではなく、代わりに .PropertyRef(...) を使用することだと思います。以下は、組織 (親) とその管理者 (子) の間の 1 対 1 の関係を定義する方法です。

HasOne(x => x.Admin).PropertyRef(r => r.Organisation).Cascade.All();

管理者は、外部キーを使用して組織への簡単な参照を持っています。

References(x => x.Organisation, "ORAD_FK_ORGANISATION").Not.Nullable();

組織を取得すると、正しい管理者レコードが読み込まれ、更新と削除が適切にカスケードされます。

于 2010-03-05T11:42:42.037 に答える
6

次を使用する必要があります。

References(x => x.Document、 "DocumentIdColumnOnTask")

于 2009-03-13T17:10:27.770 に答える
5

ここでの問題は、「HasOne」規則は、他のものを指していることを意味していることだと思います(「ManyToOne」/「OnetoOne」の標準的なリレーショナル方法)。ドキュメントにTask_IDを配置することにより、実際の関係はHasManyになりますが、タスクごとに1つのドキュメントしかないという暗黙の了解があります。

申し訳ありませんが、これを修正する方法はわかりませんが、解決策を確認したいと思います(NHibernateまたはFluent NHibernateは使用していませんが、将来使用するために調査しています)。(ほとんどアイデアのない人からの)解決策は、タスクでDocumentsをコレクションにしてから、コレクションの最初のプロパティを返すDocumentプロパティを提供することです(Documentsプロパティを非表示にするインターフェイスを使用して、誰も追加できないと考えます)。それに新しいアイテム)。

ドキュメントを調べてeulerfxの答えを検討すると、おそらくアプローチは次のようになります。

References(x => x.Document)
    .TheColumnNameIs("ID")
    .PropertyRef(d => d.Task_ID);

編集:この答えが適切な解決策を持っているように:正しいパスは、コードの意図に一致するようにデータベーススキーマを更新することです。これは、DocumentIDをタスクテーブルに追加することを意味するため、タスクとドキュメントの間には多対1の関係があります。スキーマの変更が不可能な場合は、References()が適切な解決策になります。

于 2009-03-13T17:09:33.047 に答える
2

私はこの解決策を試しました:

ドキュメント内:

mapping.HasOne(x => x.Task).ForeignKey("Task_ID").Constrained().Cascade.All();
于 2012-03-27T06:39:22.493 に答える
0

eulerfx が指摘したように、

テーブル構造は、タスクに複数のドキュメントがある可能性があることを示しています

そしてクリスは次のように述べています。

ドキュメントに Task_ID を配置することで、実際の関係は HasMany になりますが、タスクごとに 1 つのドキュメントしか存在しないという暗黙の了解が得られます。

これはもちろん正しいので、Task は null 許容の Document_Id を持つように逆にしました。

助けてくれてありがとう!

受け入れられた答えのためにコインを投げました。両方にチェックを入れることができれば、そうします!

于 2009-03-13T17:40:03.737 に答える
0

私は同じHas Oneの問題に苦労してきましたが、最終的にこれが機能することがわかりました:

public class ParentMap : ClassMap<Parent>
{
    public ParentMap()
    {
        Id(x => x.Id);
        HasOne(s => s.Child).Cascade.All();
    }
}

 public class ChildMap : ClassMap<Model.Child>
{
    public ChildMap()
    {
        Id(x => x.Id);
        HasOne(s => s.Parent).Constrained().ForeignKey();           
    }
}
于 2011-12-30T10:33:39.577 に答える