0

在成功添加其相关子项后,我目前难以跟踪父实体对象并将其添加到我的上下文中。

我有两个 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

在我的视图的左侧,我有一个 ListBox,它显示了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");
      }
  }

当用户单击其中一个选定的父程序集 ( 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();
        }
    }     

看来这实际上会保存我的 MasterPartsList 数据,如果不是因为MasterPartNumber.pn不能为空的强制外键约束。

我已经坚持了好几天了。当我只使用一张表时,我很容易实现 .SaveChanges。有没有人能明白为什么我无法添加item.MasterPartNumber(或者甚至得到一个非空对象,就此而言?)

提前致谢。请让我知道我需要进一步澄清的地方。

4

1 回答 1

0

首先,我不建议将数据加载到那里的属性 getter 中。

其次,添加时不应该将实体引用例如item.MasterPartNumber自动添加到上下文中item吗?我确信这是 EF 的常见工作方式。

您还提到了强制外键约束……那部分不是很清楚。你能提供异常消息吗?另外,您使用的是什么版本/风格 - DbContext 或 ObjectContext?先码字?自我跟踪实体?问题是外键还是主键?主键是否在数据库和 EDMX 中自动递增并标记为这样?

作为一般建议,请确保您尝试了解实体框架在幕后所做的事情;否则你会在没有真正理解原因的情况下最终讨厌它(并不是没有充分的理由)。尝试可视化您在内存中的对象图以及 EF 如何尝试跟踪所有内容的连接方式;当您保存更改并尝试找出保存所有内容所需的顺序时,它会这样做,以免违反约束。啊,但我会停止写诗,而我仍然可以保持严肃的外表。

于 2013-02-26T02:00:01.060 回答