我在调用{DataContext}.SubmitChanges()时收到stackoverflow异常...我希望我知道要发布哪些代码行来帮助澄清这种情况,但是抛出该异常时它不提供任何信息,它说:

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


然后在“查看详细信息”中,我得到:

{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列上

最佳答案

我可能不正确地读取了您的代码,但是在此代码段中,它看起来像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

关于c# - 调用.SubmitChanges()linq时获得随机堆栈溢出,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22304038/

10-13 06:05