实体框架中的慢速保存,非常具体的实体

问题描述 投票:0回答:1

我有一个很有趣(且令人困惑)的问题,但有一段时间了,但无法深入了解它

我有一个基于WPF构建的Entity Framework项目,其中包含大约100个不同的实体/表,它们均能正常运行。除了一个实体类型,即SaleProduct

保存SaleProduct大约需要5分钟,有时甚至更长(其他实体通常不到2秒)。并且仅在窗口中。

出于测试目的,我将此代码放在了应用启动时:

  Using d = GetSystemContext(True)
        Dim sp = d.Find(Of SaleProduct)(66246)
        sp.DiscountAmount += 1
        d.SaveChanges()
  End Using

并保存就可以了(11秒,可以承受)。

但是,当我打开一个将SaleProduct作为DataContext的窗口并保存在那里时,需要几分钟。

所以,我想调试一下。也许我在某处有一些错误的代码。但是我也不能解决这个问题。如果在应用程序处于保存状态时按Visual Studio中的暂停,它将冻结在SaveChanges行上,这意味着没有一些自定义代码。那么,如果我们在应用程序启动或窗口中,应该有什么区别?

但是让我们更进一步,我禁用了Just My Code以更好地了解冻结的情况。它卡在这里:

InternalDispatcher.cs

try
  {
     interceptionContext.MutableData.SetExecuted(operation(target, interceptionContext));
  }

目标是非常简单的SQL语句

UPDATE [dbo].[Sales]
SET [LastEditedOn] = @0
WHERE ([ID] = @1)
SELECT [AutoPurchaseDate], [GrantingDate], [ReceivedOn], [Name], [TotalVatRate]
FROM [dbo].[Sales]
WHERE @@ROWCOUNT > 0 AND [ID] = @1

SSMS中运行此程序需要<1秒。

但是查看完整的调用堆栈,我发现它实际上卡在System.Data.dll中的某个位置。尽管尽我所能,我找不到它的.pdb

所以我尝试使用反编译,但出现错误

无法编译模块

尽管在模块窗口中,状态为“符号已加载”。

所以我不能精确指出。

关于踢,我尝试从.4.7升级到.net 4.8。同样的问题。

我该怎么办?如何进行?我还可以在哪里调查?

非常感谢您的时间!

这是完整的StackTrace,如果它可以帮助某人,则>]

[Managed to Native Transition]  
    System.Data.dll!SNINativeMethodWrapper.SNIReadSyncOverAsync(System.Runtime.InteropServices.SafeHandle pConn, ref System.IntPtr packet, int timeout) Unknown
    System.Data.dll!System.Data.SqlClient.TdsParserStateObject.ReadSniSyncOverAsync()   Unknown
    System.Data.dll!System.Data.SqlClient.TdsParserStateObject.TryReadNetworkPacket()   Unknown
    System.Data.dll!System.Data.SqlClient.TdsParserStateObject.TryPrepareBuffer()   Unknown
    System.Data.dll!System.Data.SqlClient.TdsParserStateObject.TryReadByte(out byte value)  Unknown
    System.Data.dll!System.Data.SqlClient.TdsParser.TryRun(System.Data.SqlClient.RunBehavior runBehavior, System.Data.SqlClient.SqlCommand cmdHandler, System.Data.SqlClient.SqlDataReader dataStream, System.Data.SqlClient.BulkCopySimpleResultSet bulkCopyHandler, System.Data.SqlClient.TdsParserStateObject stateObj, out bool dataReady)  Unknown
    System.Data.dll!System.Data.SqlClient.SqlDataReader.TryConsumeMetaData()    Unknown
    System.Data.dll!System.Data.SqlClient.SqlDataReader.MetaData.get()  Unknown
    System.Data.dll!System.Data.SqlClient.SqlCommand.FinishExecuteReader(System.Data.SqlClient.SqlDataReader ds, System.Data.SqlClient.RunBehavior runBehavior, string resetOptionsString, bool isInternal, bool forDescribeParameterEncryption, bool shouldCacheForAlwaysEncrypted)    Unknown
    System.Data.dll!System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(System.Data.CommandBehavior cmdBehavior, System.Data.SqlClient.RunBehavior runBehavior, bool returnStream, bool async, int timeout, out System.Threading.Tasks.Task task, bool asyncWrite, bool inRetry, System.Data.SqlClient.SqlDataReader ds, bool describeParameterEncryptionRequest)  Unknown
    System.Data.dll!System.Data.SqlClient.SqlCommand.RunExecuteReader(System.Data.CommandBehavior cmdBehavior, System.Data.SqlClient.RunBehavior runBehavior, bool returnStream, string method, System.Threading.Tasks.TaskCompletionSource<object> completion, int timeout, out System.Threading.Tasks.Task task, out bool usedCache, bool asyncWrite, bool inRetry)   Unknown
    System.Data.dll!System.Data.SqlClient.SqlCommand.RunExecuteReader(System.Data.CommandBehavior cmdBehavior, System.Data.SqlClient.RunBehavior runBehavior, bool returnStream, string method) Unknown
    System.Data.dll!System.Data.SqlClient.SqlCommand.ExecuteReader(System.Data.CommandBehavior behavior, string method) Unknown
>   EntityFramework.dll!System.Data.Entity.Infrastructure.Interception.InternalDispatcher<System.Data.Entity.Infrastructure.Interception.IDbCommandInterceptor>.Dispatch<System.Data.Common.DbCommand, System.Data.Entity.Infrastructure.Interception.DbCommandInterceptionContext<System.Data.Common.DbDataReader>, System.Data.Common.DbDataReader>(System.Data.Common.DbCommand target, System.Func<System.Data.Common.DbCommand, System.Data.Entity.Infrastructure.Interception.DbCommandInterceptionContext<System.Data.Common.DbDataReader>, System.Data.Common.DbDataReader> operation, System.Data.Entity.Infrastructure.Interception.DbCommandInterceptionContext<System.Data.Common.DbDataReader> interceptionContext, System.Action<System.Data.Entity.Infrastructure.Interception.IDbCommandInterceptor, System.Data.Common.DbCommand, System.Data.Entity.Infrastructure.Interception.DbCommandInterceptionContext<System.Data.Common.DbDataReader>> executing, System.Action<System.Data.Entity.Infrastructure.Interception.IDbCommandInterceptor, System.Data.Common.DbCommand, System.Data.Entity.Infrastructure.Interception.DbCommandInterceptionContext<System.Data.Common.DbDataReader>> executed) Line 138  C#
    EntityFramework.dll!System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.Reader(System.Data.Common.DbCommand command, System.Data.Entity.Infrastructure.Interception.DbCommandInterceptionContext interceptionContext) Line 103   C#
    EntityFramework.dll!System.Data.Entity.Core.Mapping.Update.Internal.DynamicUpdateCommand.Execute(System.Collections.Generic.Dictionary<int, object> identifierValues, System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<System.Data.Entity.Core.Mapping.Update.Internal.PropagatorResult, object>> generatedValues) Line 118  C#
    EntityFramework.dll!System.Data.Entity.Core.Mapping.Update.Internal.UpdateTranslator.Update() Line 532  C#
    EntityFramework.dll!System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction<int>(System.Func<int> func, System.Data.Entity.Infrastructure.IDbExecutionStrategy executionStrategy, bool startLocalTransaction, bool releaseConnectionOnSuccess) Line 2203 C#
    EntityFramework.dll!System.Data.Entity.Core.Objects.ObjectContext.SaveChangesToStore(System.Data.Entity.Core.Objects.SaveOptions options, System.Data.Entity.Infrastructure.IDbExecutionStrategy executionStrategy, bool startLocalTransaction) Line 2148   C#
    EntityFramework.SqlServer.dll!System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute<int>(System.Func<int> operation) Unknown
    EntityFramework.dll!System.Data.Entity.Core.Objects.ObjectContext.SaveChangesInternal(System.Data.Entity.Core.Objects.SaveOptions options, bool executeInExistingTransaction) Line 2046 C#
    EntityFramework.dll!System.Data.Entity.Internal.InternalContext.SaveChanges() Line 483  C#
    Machshevet.dll!Machshevet.Core.RecordContext.SaveChanges() Line 762 Basic
    Machshevet.dll!Machshevet.Windows.RecordWindow.Save() Line 169  Basic
    Machshevet.dll!Machshevet.Windows.RecordWindow.<closure>.<lambda35-0>() Line 44 Basic
    PresentationCore.dll!System.Windows.Input.CommandBinding.OnExecuted(object sender, System.Windows.Input.ExecutedRoutedEventArgs e)  Unknown
    PresentationCore.dll!System.Windows.Input.CommandManager.ExecuteCommandBinding(object sender, System.Windows.Input.ExecutedRoutedEventArgs e, System.Windows.Input.CommandBinding commandBinding)   Unknown
    PresentationCore.dll!System.Windows.Input.CommandManager.FindCommandBinding(System.Windows.Input.CommandBindingCollection commandBindings, object sender, System.Windows.RoutedEventArgs e, System.Windows.Input.ICommand command, bool execute)    Unknown
    PresentationCore.dll!System.Windows.Input.CommandManager.FindCommandBinding(object sender, System.Windows.RoutedEventArgs e, System.Windows.Input.ICommand command, bool execute)   Unknown
    PresentationCore.dll!System.Windows.Input.CommandManager.OnExecuted(object sender, System.Windows.Input.ExecutedRoutedEventArgs e)  Unknown
    PresentationCore.dll!System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate handler, object target)   Unknown
    PresentationCore.dll!System.Windows.RoutedEventHandlerInfo.InvokeHandler(object target, System.Windows.RoutedEventArgs routedEventArgs) Unknown
    PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source, System.Windows.RoutedEventArgs args, bool reRaised)    Unknown
    PresentationCore.dll!System.Windows.UIElement.RaiseEventImpl(System.Windows.DependencyObject sender, System.Windows.RoutedEventArgs args)   Unknown
    PresentationCore.dll!System.Windows.Input.RoutedCommand.ExecuteImpl(object parameter, System.Windows.IInputElement target, bool userInitiated)  Unknown
    PresentationCore.dll!System.Windows.Input.CommandManager.TransferEvent(System.Windows.IInputElement newSource, System.Windows.Input.ExecutedRoutedEventArgs e)  Unknown
    PresentationCore.dll!System.Windows.Input.CommandManager.OnExecuted(object sender, System.Windows.Input.ExecutedRoutedEventArgs e)  Unknown
    PresentationCore.dll!System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate handler, object target)   Unknown
    PresentationCore.dll!System.Windows.RoutedEventHandlerInfo.InvokeHandler(object target, System.Windows.RoutedEventArgs routedEventArgs) Unknown
    PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source, System.Windows.RoutedEventArgs args, bool reRaised)    Unknown
    PresentationCore.dll!System.Windows.UIElement.RaiseEventImpl(System.Windows.DependencyObject sender, System.Windows.RoutedEventArgs args)   Unknown
    PresentationCore.dll!System.Windows.Input.RoutedCommand.ExecuteImpl(object parameter, System.Windows.IInputElement target, bool userInitiated)  Unknown
    PresentationFramework.dll!MS.Internal.Commands.CommandHelpers.CriticalExecuteCommandSource(System.Windows.Input.ICommandSource commandSource, bool userInitiated)   Unknown
    PresentationFramework.dll!System.Windows.Controls.Primitives.ButtonBase.OnClick()   Unknown
    PresentationFramework.dll!System.Windows.Controls.Button.OnClick()  Unknown
    System.Windows.Controls.Ribbon.dll!System.Windows.Controls.Ribbon.RibbonButton.OnClick()    Unknown
    PresentationFramework.dll!System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(System.Windows.Input.MouseButtonEventArgs e)    Unknown
    PresentationCore.dll!System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate handler, object target)   Unknown
    PresentationCore.dll!System.Windows.RoutedEventHandlerInfo.InvokeHandler(object target, System.Windows.RoutedEventArgs routedEventArgs) Unknown
    PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source, System.Windows.RoutedEventArgs args, bool reRaised)    Unknown
    PresentationCore.dll!System.Windows.UIElement.ReRaiseEventAs(System.Windows.DependencyObject sender, System.Windows.RoutedEventArgs args, System.Windows.RoutedEvent newEvent)  Unknown
    PresentationCore.dll!System.Windows.UIElement.OnMouseUpThunk(object sender, System.Windows.Input.MouseButtonEventArgs e)    Unknown
    PresentationCore.dll!System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate handler, object target)   Unknown
    PresentationCore.dll!System.Windows.RoutedEventHandlerInfo.InvokeHandler(object target, System.Windows.RoutedEventArgs routedEventArgs) Unknown
    PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source, System.Windows.RoutedEventArgs args, bool reRaised)    Unknown
    PresentationCore.dll!System.Windows.UIElement.RaiseEventImpl(System.Windows.DependencyObject sender, System.Windows.RoutedEventArgs args)   Unknown
    PresentationCore.dll!System.Windows.UIElement.RaiseTrustedEvent(System.Windows.RoutedEventArgs args)    Unknown
    PresentationCore.dll!System.Windows.Input.InputManager.ProcessStagingArea() Unknown
    PresentationCore.dll!System.Windows.Input.InputManager.ProcessInput(System.Windows.Input.InputEventArgs input)  Unknown
    PresentationCore.dll!System.Windows.Input.InputProviderSite.ReportInput(System.Windows.Input.InputReport inputReport)   Unknown
    PresentationCore.dll!System.Windows.Interop.HwndMouseInputProvider.ReportInput(System.IntPtr hwnd, System.Windows.Input.InputMode mode, int timestamp, System.Windows.Input.RawMouseActions actions, int x, int y, int wheel)   Unknown
    PresentationCore.dll!System.Windows.Interop.HwndMouseInputProvider.FilterMessage(System.IntPtr hwnd, MS.Internal.Interop.WindowMessage msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled)   Unknown
    PresentationCore.dll!System.Windows.Interop.HwndSource.InputFilterMessage(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled)    Unknown
    WindowsBase.dll!MS.Win32.HwndWrapper.WndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) Unknown
    WindowsBase.dll!MS.Win32.HwndSubclass.DispatcherCallbackOperation(object o) Unknown
    WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs)  Unknown
    WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.TryCatchWhen(object source, System.Delegate callback, object args, int numArgs, System.Delegate catchHandler) Unknown
    WindowsBase.dll!System.Windows.Threading.Dispatcher.LegacyInvokeImpl(System.Windows.Threading.DispatcherPriority priority, System.TimeSpan timeout, System.Delegate method, object args, int numArgs)   Unknown
    WindowsBase.dll!MS.Win32.HwndSubclass.SubclassWndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam)  Unknown
    [Native to Managed Transition]  
    [Managed to Native Transition]  
    WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame frame)   Unknown
    PresentationFramework.dll!System.Windows.Application.RunDispatcher(object ignore)   Unknown
    PresentationFramework.dll!System.Windows.Application.RunInternal(System.Windows.Window window)  Unknown

一段时间以来,我有一个非常有趣(令人困惑)的问题,但不能深入了解,我有一个基于Entity Framework的WPF项目,其中包含约100个不同的实体/表,...]]] >

对此问题的具体答案将需要查看负责的特定代码。除了在DbContext和数据库架构中表已定义的关系以及DbContext跟踪的当前状态之外,单个表可能不是问题。 (以及数据库可能正在锁定的内容,尽管通常这是一种更为间歇的问题)

要检查的一些事情:在您的App示例中,您似乎正在获取DbContext的新实例并进行处理。 (良好)11s时间反映的是Find + Save,还是只是Save? DbContext在应用程序中执行的第一个查询会产生1-off(认为是静态的)启动成本以初始化模型。为了在首次运行时更准确地计时,您可以执行以下操作:

Using d = GetSystemContext(True)
    Dim dump = d.Sales.Any()
    ' Start timing here...
    Dim sp = d.Find(Of SaleProduct)(66246)
    sp.DiscountAmount += 1
    d.SaveChanges()
    ' End timing here...
End Using

*抱歉,我的VB.Net已经过时了..::)在任何情况下,对DbContext进行快速操作(如Any())都会产生一次性的启动费用。之后的任何操作都应更纯粹地表示加载和保存数据所需的时间。

在您有问题的代码中,是否保证DbContext这样短命?存活时间更长的DbContext会引用多个实体,并且只要任何实体持久存在,它就会搜索实体树,以确定是否需要更新任何相关实体。短命的,易处理的DbContext是要走的路。

您是否对数据库运行了探查器以捕获正在运行的确切SQL?您的示例SQL看起来不像EF查询,而是引用“ Sales”表而不是“ SalesProduct”。在调试EF应用程序操作时运行探查器对于揭示意外情况背后发生的事情非常有用。

其他可能性实际上取决于所讨论的代码,但是将探查器与断点结合使用通常可以帮助发现问题。是否确定延迟仅发生在DbContext.SaveChanges发生或整个保存过程中?如果是从用户单击“保存”按钮起的某个时间,则探查器可能会发现您的代码触发了许多延迟加载调用(加载数据以进行保存之前进行检查和更新)或加载意外数据。 (我见过的常见问题是在过滤语句之前将ToList()调用放错了位置,通常是因为开发人员想要执行EF无法翻译的操作,并且ToList()似乎是“修复”。)如果延迟只是来自SaveChanges,则探查器可以确认生成了哪些Update语句以及它们需要运行多长时间。

sql-server entity-framework
1个回答
0
投票

对此问题的具体答案将需要查看负责的特定代码。除了在DbContext和数据库架构中表已定义的关系以及DbContext跟踪的当前状态之外,单个表可能不是问题。 (以及数据库可能正在锁定的内容,尽管通常这是一种更为间歇的问题)

© www.soinside.com 2019 - 2024. All rights reserved.