【发布时间】:2013-02-26 00:29:29
【问题描述】:
在成功添加其相关子对象后,我目前难以跟踪父实体对象并将其添加到我的上下文中。
我有两个 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,它显示所有 assembly 或 parent 实体对象的 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");
}
}
Selected Parent Assembly 由 viewmodel 属性定义:
public MasterPartNumber SelectedTopLevelAssyPN
{
get { return this._selectedTopLevelAssyPN; }
set
{
this._selectedTopLevelAssyPN = value;
RaisePropertyChanged("SelectedTopLevelAssyPN");
RaisePropertyChanged("SelectedAssyBOMLineItems");
}
}
当用户单击其中一个选定的父程序集 (SelectedTopLevelAssyPN) 时,DataGrid 会显示绑定到所有子实体的ObservableCollection,其父实体(由属性parentAssyPN 给出)是SelectedTopLevelAssyPN。
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(或者甚至无法获得非空对象?)
提前致谢。请让我知道我需要进一步澄清的地方。
【问题讨论】:
标签: c# entity-framework-4 parent-child observablecollection savechanges