0

関連する子を正常に追加した後、現在、親エンティティオブジェクトを追跡してコンテキストに追加するのに問題があります。

外部キーによって関連付けられているエンティティにマップされた2つのSQLテーブルがあります。

 MasterPartNumber (parent, one) --> MasterPartsList (children, many)
  (PK) pn <--short for PartNumber     (PK) listID
       pnDesc                         (FK) pn
       docNum                              parentAssyPN <-- if null, means it is the "top level assembly"
                                           findNum
                                           qty
                                           isAssy

ビューの左側には、ObservableCollectionすべてのアセンブリまたはエンティティオブジェクトのを表示するリストボックスがあります。次のようになります。

    public ObservableCollection<MasterPartNumber> AssyPns
    {
        get
        {
                var enumerable = this._context.MasterPartNumbers.Where(x => x.isAssy == true);

                return this._assyPns = new ObservableCollection<MasterPartNumber>(enumerable);
        }
        set 
        {
            this._assyPns = value;
            RaisePropertyChanged("AssyPns");  
        }
    }

選択された親アセンブリは、viewmodelプロパティによって定義されます。

 public MasterPartNumber SelectedTopLevelAssyPN 
 {
      get { return this._selectedTopLevelAssyPN; }
      set
      {
          this._selectedTopLevelAssyPN = value;
          RaisePropertyChanged("SelectedTopLevelAssyPN");
          RaisePropertyChanged("SelectedAssyBOMLineItems");
      }
  }

ユーザーが選択した親アセンブリ()の1つをクリックするSelectedTopLevelAssyPNと、DataGridは、親(プロパティで指定)がObservableCollectionであるすべての子エンティティへのバインドを表示します。parentAssyPNSelectedTopLevelAssyPN

 public ObservableCollection<MasterPartsList> SelectedAssyBOMLineItems
    {
        get
        {
            if (this._selectedTopLevelAssyPN != null)
            {
                var children = _context.MasterPartsLists.Where(lineItem => lineItem.parentAssyPN == this._selectedTopLevelAssyPN.pn);
                return this._selectedAssyBOMLineItems = new ObservableCollection<MasterPartsList>(children);

            }
            return this._selectedAssyBOMLineItems;
        }
        set
        {
            this._selectedAssyBOMLineItems = value;
            RaisePropertyChanged("SelectedAssyBOMLineItems");
        }
    }

コレクションのプロパティを移動して、外部キーを含むエンティティ(ここに私のxaml)まで移動できることに注目してください。

             <DataGrid x:Name="lineItemDataEntryGrid" Grid.Row="0"
                  Margin="15,15,15,0"
                  AutoGenerateColumns="False"
                  EnableRowVirtualization="True"
                  Width="Auto"
                  ItemsSource="{Binding SelectedAssyBOMLineItems, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                  >
            <DataGrid.Columns>
                <DataGridTextColumn x:Name="qtyReadColumn" 
                                    Binding="{Binding qty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                    Width="SizeToHeader"
                                    Header="QTY REQ'D"/>
                <DataGridTextColumn x:Name="partOrIDNumColumn" 
                                    Binding="{Binding pn, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                    Width="SizeToHeader"
                                    Header="PART OR IDENTIFYING NUMBER"/>

                <DataGridTextColumn x:Name="partNumDescColumn" 
                                    Binding="{Binding MasterPartNumber.pnDesc, Mode= TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                    Width="SizeToHeader"
                                    Header="NOMENCALTURE OR DESCRIPTION"/>
                <DataGridTextColumn x:Name="docNumColumn" 
                                    Binding="{Binding MasterPartNumber.docNum, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                    Width="SizeToHeader"
                                    Header="INTERNAL DOCUMENTATION"/>
                <DataGridTemplateColumn x:Name="isAssyColumn" 
                                        Header="IS ASSEMBLY? "
                                        Width="30"
                                        >
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <CheckBox IsChecked="{Binding isAssy}" IsThreeState="False" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>

            </DataGrid.Columns>

        </DataGrid>

そして、すべてが正しく表示されます。つまり、親エンティティから子エンティティに効果的に移動しているということです。

今私の問題:新しいアイテムをからに完全に追加することはできMasterPartsListますcontextが、MasterPartNumberオブジェクトを追加することはできません。

SaveCommand(リレーコマンド)のコードは次のようになります。

    private void SaveLineItems()
    {
        //update the parts list if any Object properties have been edited

        foreach (MasterPartsList item in this._selectedAssyBOMLineItems)
        {
            this._context.DetectChanges();
            this._context.MasterPartsLists.AddObject(item);
          //  this._context.MasterPartNumbers.AddObject(item.MasterPartNumber); //Doesn't work: pnMatch.MasterPartNumber is null & Throws NullReferenceException
            this._context.SaveChanges();
        }
    }     

MasterPartNumber.pnnullにできない強制外部キー制約がなければ、これにより実際にMasterPartsListデータが保存されるようです。

私はこれに何日も立ち往生しています。1つのテーブルで作業しているときに、.SaveChangesを簡単に実装できました。なぜ私が追加できないitem.MasterPartNumberのか(さらに言えば、null以外のオブジェクトを取得できないのか)を誰かが理解できますか?

前もって感謝します。さらに詳しい説明が必要な箇所を教えてください。

4

1 に答える 1

0

まず第一に、そこのプロパティゲッターにデータをロードすることはお勧めしません。

item.MasterPartNumber次に、追加するときにコンテキストに自動的に追加されるなどのエンティティ参照をすべきではありませんitemか?それがEFの一般的な仕組みだと確信しています。

また、強制された外部キー制約についても言及しています...その部分はあまり明確ではありません。例外メッセージを提供できますか?また、使用しているバージョン/フレーバー-DbContextまたはObjectContext?最初にコーディングしますか?自己追跡エンティティ?問題なのは外部キーですか、それとも主キーですか?主キーは自動インクリメントされ、データベースとEDMXの両方でそのようにマークされていますか?

一般的なアドバイスとして、EntityFrameworkが内部で何をしているのかを理解するようにしてください。そうしないと、理由を本当に理解せずにそれを嫌うことになります(正当な理由がないわけではありません)。メモリ内にあるオブジェクトグラフと、EFがすべてがどのように接続されているかを追跡しようとする方法を視覚化してみてください。これは、変更を保存し、制約に違反しないようにすべてを保存する必要がある順序を把握しようとするときに行われます。ああ、でも真面目さを保っている間は、詩的なワックスがけをやめます。

于 2013-02-26T02:00:01.060 に答える