调用时会出现随机堆栈溢出.SubmitChanges()linq

时间:2014-03-10 15:15:15

标签: c# linq stack-overflow

我在调用{DataContext}.SubmitChanges()时遇到了stackoverflow异常...我希望我知道要发布哪些代码行以帮助澄清情况,但异常在抛出它时没有提供任何信息:

An unhandled exception of type 'System.StackOverflowException' occurred in mscorlib.dll

然后在View Detail中得到:

{Cannot evaluate expression because the current thread is in a stack overflow state.}

我查看了此视图模型中的所有属性,以确保所有内容都已正确声明,并且没有导致stackoverflow异常的问题......仅在调用SubmitChanges()之后才会发生。

以下是调用提交的代码:

public void VerifyAdvancePaymentsAndSave()
        {
            try
            {
                if (!VerifyTakeHomeActualBreakDownForAdvancePayments())
                {
                    MessageBox.Show(
                        "Cash, Check, and Money Order fields must add up to the amount in the Take Home Actual field!",
                        "Validation Error!", MessageBoxButton.OK, MessageBoxImage.Exclamation);

                    return;
                }

                if (MessageBox.Show("Are you sure you want to save this payment?", "Save", MessageBoxButton.YesNo, MessageBoxImage.Question) != MessageBoxResult.Yes)
                    return;

                if (!UserController.CreateUserController().CheckAccess(UserController.RestrictedAccessAction.EditCollections))
                {
                    return;
                }

                if (InitialCollectionAction == CollectionAction.ViewAdvancePayment)
                {
                    foreach (Advance a in Advances)
                    {
                        foreach (AdvancePayment ap in a.AdvancePayments)
                        {
                            AdvancePayment newAP = sp.AdvancePayments.Where(adv => adv.Id == ap.Id).SingleOrDefault();

                            if (newAP != null)
                            {
                                newAP.Payment = ap.Payment;
                                newAP.IsSaved = false;
                            }
                            else
                            {
                                MessageBox.Show("Could not find Advance Payment to apply amount to!");
                                return;
                            }
                        }
                    }
                }
                else
                {
                    try
                    {
                        CurrentCollection.Status = BatchStatus.Open.ToString();
                        CurrentCollection.CollectionDate = DateTime.Now;
                        CurrentCollection.IsAdvancedPayment = true;
                        CurrentCollection.CollectionMachines = null;


                        //sp.Collections.InsertOnSubmit(CurrentCollection);
                    }
                    catch
                    {
                        MessageBox.Show("Error inserting changes!");
                    }
                }

                try
                {
                    sp.SubmitChanges();

                    if (InitialCollectionAction == CollectionAction.ViewAdvancePayment)
                        MessageBox.Show("Advance Payment was saved Successfully!");
                    else
                        MessageBox.Show("Advance Payment was submitted Sucessfully!");

                    CloseTab();
                }
                catch
                {
                    MessageBox.Show("Error submitting changes!");
                }
            }
            catch (Exception ex)
            {
                string message = UserController.CreateUserController().LoggedInUser.UserName + "\n" + ex.Message + "\n" + ex.StackTrace;
                EmailController.CreateEmailController().SendEmail("URM Error", message);
            }
        }

堆栈跟踪 - 在SubmitChanges()调用之前

   at URM.ViewModels.CollectionsViewModel.VerifyAdvancePaymentsAndSave()
   at URM.Commands.CollectionsSaveCommand.Execute(Object parameter)
   at MS.Internal.Commands.CommandHelpers.CriticalExecuteCommandSource(ICommandSource commandSource, Boolean userInitiated)
   at System.Windows.Controls.Primitives.ButtonBase.OnClick()
   at System.Windows.Controls.Button.OnClick()
   at System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(MouseButtonEventArgs e)
   at System.Windows.UIElement.OnMouseLeftButtonUpThunk(Object sender, MouseButtonEventArgs e)
   at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.ReRaiseEventAs(DependencyObject sender, RoutedEventArgs args, RoutedEvent newEvent)
   at System.Windows.UIElement.OnMouseUpThunk(Object sender, MouseButtonEventArgs e)
   at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
   at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
   at System.Windows.Input.InputManager.ProcessStagingArea()
   at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
   at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
   at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)
   at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
   at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.Run()
   at System.Windows.Application.RunDispatcher(Object ignore)
   at System.Windows.Application.RunInternal(Window window)
   at System.Windows.Application.Run(Window window)
   at System.Windows.Application.Run()
   at URM.App.Main()
   at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
   at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
   at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

此视图模型中使用的模型:

public class AdvancePaymentsModel : INotifyPropertyChanged
    {
        public int AdvanceId { get; set; }
        public string PaymentId { get; set; }
        public decimal Payment { get; set; }
        public DateTime PaymentDate { get; set; }

        private string _status;
        public string Status
        {
            get
            {
                return _status;
            }

            set
            {
                _status = value;
                OnPropertyChanged("Status");
            }
        }

        private Brush _brushObj;
        public Brush BrushObj
        {
            get
            {
                return _brushObj;
            }

            set
            {
                _brushObj = value;
                OnPropertyChanged("BrushObj");
            }
        }

        private AdvancePayment _advancePayment;
        public AdvancePayment AdvancePayment
        {
            get
            {
                return _advancePayment;
            }

            set
            {
                _advancePayment = value;
                OnPropertyChanged("AdvancePayment");
            }
        }

        private Visibility _voidButtonVisibility;
        public Visibility VoidButtonVisibility
        {
            get
            {
                return _voidButtonVisibility;
            }

            set
            {
                _voidButtonVisibility = value;
                OnPropertyChanged("VoidButtonVisibility");
            }
        }
}

public class AdvancePaymentsModel : INotifyPropertyChanged
    {
        public int AdvanceId { get; set; }
        public string PaymentId { get; set; }
        public decimal Payment { get; set; }
        public DateTime PaymentDate { get; set; }

        private string _status;
        public string Status
        {
            get
            {
                return _status;
            }

            set
            {
                _status = value;
                OnPropertyChanged("Status");
            }
        }

        private Brush _brushObj;
        public Brush BrushObj
        {
            get
            {
                return _brushObj;
            }

            set
            {
                _brushObj = value;
                OnPropertyChanged("BrushObj");
            }
        }

        private AdvancePayment _advancePayment;
        public AdvancePayment AdvancePayment
        {
            get
            {
                return _advancePayment;
            }

            set
            {
                _advancePayment = value;
                OnPropertyChanged("AdvancePayment");
            }
        }

        private Visibility _voidButtonVisibility;
        public Visibility VoidButtonVisibility
        {
            get
            {
                return _voidButtonVisibility;
            }

            set
            {
                _voidButtonVisibility = value;
                OnPropertyChanged("VoidButtonVisibility");
            }
        }
     }
}

启用调试.Net Framework源代码后...我看到在调度程序类中抛出了stackoverflow异常

 private void PushFrameImpl(DispatcherFrame frame) 
        {
            SynchronizationContext oldSyncContext = null;
            SynchronizationContext newSyncContext = null;
            MSG msg = new MSG(); 

            _frameDepth++; 
            try 
            {
                // Change the CLR SynchronizationContext to be compatable with our Dispatcher. 
                oldSyncContext = SynchronizationContext.Current;
                newSyncContext = new DispatcherSynchronizationContext(this);
                SynchronizationContext.SetSynchronizationContext(newSyncContext);

                try
                { 
                    while(frame.Continue) 
                    {
                        if (!GetMessage(ref msg, IntPtr.Zero, 0, 0)) 
                            break;

                        TranslateAndDispatchMessage(ref msg); //*<--------- gets thrown here*
                    } 

                    // If this was the last frame to exit after a quit, we 
                    // can now dispose the dispatcher. 
                    if(_frameDepth == 1)
                    { 
                        if(_hasShutdownStarted)
                        {
                            ShutdownImpl();
                        } 
                    }
                } 
                finally 
                {
                    // Restore the old SynchronizationContext. 
                    SynchronizationContext.SetSynchronizationContext(oldSyncContext);
                }
            }
            finally 
            {
                _frameDepth--; 
                if(_frameDepth == 0) 
                {
                    // We have exited all frames. 
                    _exitAllFrames = false;
                }
            }
        } 

在调度程序崩溃后,这里是堆栈跟踪:

    [Managed to Native Transition]  
    WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame frame) Line 2281 + 0x35 bytes    Unknown
    WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame frame) Line 368 + 0x9 bytes  Unknown
    WindowsBase.dll!System.Windows.Threading.Dispatcher.Run() Line 327 + 0x34 bytes Unknown
>   PresentationFramework.dll!System.Windows.Application.RunDispatcher(object ignore) Line 2745 C#
    PresentationFramework.dll!System.Windows.Application.RunInternal(System.Windows.Window window) Line 1841    C#
    PresentationFramework.dll!System.Windows.Application.Run(System.Windows.Window window) Line 261 + 0x9 bytes C#
    PresentationFramework.dll!System.Windows.Application.Run() Line 222 + 0x15 bytes    C#
    URM.exe!URM.App.Main() + 0x59 bytes C#
    [Native to Managed Transition]  
    [Managed to Native Transition]  
    mscorlib.dll!System.AppDomain.ExecuteAssembly(string assemblyFile, System.Security.Policy.Evidence assemblySecurity, string[] args) + 0x6b bytes    
    Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() + 0x27 bytes  
    mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object state) + 0x6f bytes   
    mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) + 0xa7 bytes  
    mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) + 0x16 bytes  
    mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x41 bytes    
    mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() + 0x44 bytes   
    [Native to Managed Transition]  

所以在听完@KellyGendron和@David的建议后,我最终得到了在ChangeTracker类中抛出的stackoverflow异常

 internal override bool IsMemberPendingGeneration(MetaDataMember keyMember) {
                    if (this.IsNew && keyMember.IsDbGenerated) { 
                        return true;
                    }
                    // look for any FK association that has this key member (should only be one)
                    foreach (MetaAssociation assoc in type.Associations) { 
                        if (assoc.IsForeignKey) {
     /*CRASHES HERE*/      int index = assoc.ThisKey.IndexOf(keyMember); 
                            if (index > -1) { 
                                // we must have a reference to this other object to know if its side of
                                // the association is generated or not 
                                object otherItem = null;
                                if (assoc.ThisMember.IsDeferred) {
                                    otherItem = assoc.ThisMember.DeferredValueAccessor.GetBoxedValue(this.current);
                                } 
                                else {
                                    otherItem = assoc.ThisMember.StorageAccessor.GetBoxedValue(this.current); 
                                } 
                                if (otherItem != null) {
                                    if (assoc.IsMany) { 
                                        // Can't be pending generation for a value that would have to be the same
                                        // across many rows.
                                        continue;
                                    } 
                                    else {
                                        StandardTrackedObject trackedOther = (StandardTrackedObject)this.tracker.GetTrackedObject(otherItem); 
                                        if (trackedOther != null) { 
                                            MetaDataMember otherMember = assoc.OtherKey[index];
                                            return trackedOther.IsMemberPendingGeneration(otherMember); 
                                        }
                                    }
                                }
                            } 
                        }
                    } 
                    return false; 
                }
            } 
        }

关键成员似乎是我可以从其部分可用的属性中得到的是Location类(数据库表),它似乎卡在ID列上

2 个答案:

答案 0 :(得分:0)

我可能会错误地阅读您的代码,但是在这个代码片段中看起来像newAP.Payment会指向自己,这可能会让串行器如此混乱。如果我误读的话,请再次原谅我,今天睡眠不足。

foreach (AdvancePayment ap in a.AdvancePayments)
    {
        AdvancePayment newAP = sp.AdvancePayments
            .Where(adv => adv.Id == ap.Id).SingleOrDefault();
        if (newAP != null)
        {
            newAP.Payment = ap.Payment;
            ...

如果不是这种情况,您可能希望尝试将保存分成多个部分,例如将关联设置为null,然后按ID指定。这里有类似的案例可能会有所帮助...... http://social.msdn.microsoft.com/Forums/silverlight/en-US/d4438aaa-a916-4335-b182-ded75f162c2d/datacontextsubmitchanges-throws-stack-overflow-exception-on-rather-simple-insert

答案 1 :(得分:0)

经过多次工作 - 最终成为一个问题,其中一个表有一个外键到它自己的主键。这导致循环引用发生。我发现调试这个的最好方法是启用.NET源代码的调试,然后我不得不在我的ViewModel中的OnPropertyChanged方法中放置一个断点。那时,我能够在ChangeaTracker类中获得异常,否则它将在Dispatcher类中中断...

相关问题