Adding New row to a datagrid cause exception

Jan 18, 2009 at 5:44 PM


  I am writing an App with Datagrids to perform standard CRUD operation on data fetched from a database. I have a datagrid with datasource is directly bound from a database table from a LinQ query.  I handle database changes through calls to commit changes to the LinQ datacontext and so far so good. Data can be deleted this way and that's fine also. (SubmitChanges are called in the RowEditEnding event of the grid)

   When inserting data, I get a row datasource that not in the datacontext changeset. I update some foreign key fields so that the data can be inserted properly in teh database, and call a datacontext.table.insertonsubmit (myrow).

   The call to SubmitChanges is sucessfull. However after returning from the RowEditEnding event, the datagrid throw an exception stating that it cannot insert an existing data. I cannot catch this exception since it's not thrown from my code. However upon restarting the application the data has been properly inserted in the database.

   Below is the top of the exception Stack is it's of any help.

A first chance exception of type 'System.InvalidOperationException' occurred in System.Data.Linq.dll
System.Transactions Critical: 0 : <TraceRecord xmlns="" Severity="Critical"><TraceIdentifier></TraceIdentifier><Description>Exception non gérée</Description><AppDomain>InProd_II.vshost.exe</AppDomain><Exception><ExceptionType>System.InvalidOperationException, mscorlib, Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType><Message>Impossible d'ajouter une entité qui existe déjà.</Message><StackTrace> à System.Data.Linq.Table`1.InsertOnSubmit(TEntity entity)
à System.Data.Linq.Provider.DataBindingList`1.EndNew(Int32 itemIndex)
à System.Windows.Data.BindingListCollectionView.CommitNew()
à System.Windows.Controls.ItemCollection.System.ComponentModel.IEditableCollectionView.CommitNew()
à Microsoft.Windows.Controls.DataGrid.CommitRowItem()
à Microsoft.Windows.Controls.DataGrid.OnExecutedCommitEdit(ExecutedRoutedEventArgs e)
à Microsoft.Windows.Controls.DataGrid.OnExecutedCommitEdit(Object sender, ExecutedRoutedEventArgs e)
à System.Windows.Input.CommandBinding.OnExecuted(Object sender, ExecutedRoutedEventArgs e)
à System.Windows.Input.CommandManager.ExecuteCommandBinding(Object sender, ExecutedRoutedEventArgs e, CommandBinding commandBinding)
à System.Windows.Input.CommandManager.FindCommandBinding(CommandBindingCollection commandBindings, Object sender, RoutedEventArgs e, ICommand command, Boolean execute)
à System.Windows.Input.CommandManager.FindCommandBinding(Object sender, RoutedEventArgs e, ICommand command, Boolean execute)
à System.Windows.Input.CommandManager.OnExecuted(Object sender, ExecutedRoutedEventArgs e)
à System.Windows.UIElement.OnExecutedThunk(Object sender, ExecutedRoutedEventArgs e)
à System.Windows.Input.ExecutedRoutedEventArgs.InvokeEventHandler(Delegate genericHandler, Object target)
à System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
à System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
à System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
à System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
à System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
à System.Windows.Input.RoutedCommand.ExecuteImpl(Object parameter, IInputElement target, Boolean userInitiated)
à System.Windows.Input.RoutedCommand.Execute(Object parameter, IInputElement target)
à Microsoft.Windows.Controls.DataGrid.EndEdit(RoutedCommand command, DataGridCell cellContainer, DataGridEditingUnit editingUnit, Boolean exitEditMode)
à Microsoft.Windows.Controls.DataGrid.CommitEdit(DataGridEditingUnit editingUnit, Boolean exitEditingMode)
à Microsoft.Windows.Controls.DataGrid.CommitAnyEdit()
à Microsoft.Windows.Controls.DataGrid.OnEnterKeyDown(KeyEventArgs e)
à Microsoft.Windows.Controls.DataGrid.OnKeyDown(KeyEventArgs e)

I guess the RowEditEnding Event was called somewhere in the middle of this before commiting the changes.

S. Barthes

Jan 21, 2009 at 2:01 PM
Could you post more of your code.  It is not really easy to tell from this stacktrace alone since this seems to be a standard call stack for committing a row.
Jan 21, 2009 at 11:28 PM


  After discussing the matter with a friend he suggested using an observable collection instead of directly using the linq collection. so I changed my code from 

<Original code that produce the error in the datagrid>

  Public Property QuotationExtCharges() As IQueryable(Of TblLigneDevisCR)
Dim RetVal As IQueryable(Of TblLigneDevisCR) = Nothing
If _QuotationExtCharges Is Nothing Then
Return RetVal

End If

  RetVal = (From Q In _QuotationExtCharges Select Q)

Return RetVal
End Get
Set(ByVal value As IQueryable(Of TblLigneDevisCR))
_QuotationExtCharges = value
RaiseEvent PropertyChanged(Me, HeaderPropsEvent(HeaderEvtEnum.ExtCharges))
End Set
End Property

< Newer code that does not produce an exception in the datagrid>

  Public Property QuotationExtCharges() As ObservableCollection(Of TblLigneDevisCR)
Dim RetVal As ObservableCollection(Of TblLigneDevisCR) = Nothing
If _QuotationExtCharges Is Nothing Then
Return RetVal

End If
RetVal = New ObservableCollection(Of TblLigneDevisCR)(From Q In _QuotationExtCharges Select Q)

Return RetVal
End Get
Set(ByVal value As ObservableCollection(Of TblLigneDevisCR))
_QuotationExtCharges = value
RaiseEvent PropertyChanged(Me, HeaderPropsEvent(HeaderEvtEnum.ExtCharges))
End Set
End Property

I can now insert data with no problem however exception are raised twice when some data cannot be inserted in the database. Sucessful updates only raise the event once.

The code I have in the rowendediting event is below:

  Private Sub LinQRowEdited(ByVal sender As System.Object, ByVal e As Microsoft.Windows.Controls.DataGridRowEditEndingEventArgs)

Static LastInSertedOptionID As Decimal = 0

If e.EditAction = Microsoft.Windows.Controls.DataGridEditAction.Commit Then
If sender Is Me.ExtChargesGrid Then

If Model Is Nothing OrElse Model.ViewedQuote Is Nothing Then
End If

If TypeOf e.Row.DataContext Is TblLigneDevisCR Then

Dim CurCr As TblLigneDevisCR = CType(e.Row.DataContext, TblLigneDevisCR)

If CurCr.IdLigneDevisCR = 0 Then
'Add a new CR Line
Model.ViewedQuote.AddCR(CurCr, LastInSertedOptionID)
End If


End If
End If
End If
End Sub

Let me know if you need more