You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: powerapps-docs/developer/data-platform/troubleshoot-plug-in.md
+8-8Lines changed: 8 additions & 8 deletions
Original file line number
Diff line number
Diff line change
@@ -38,9 +38,9 @@ This error simply means that the worker process running your plug-in code crashe
38
38
39
39
As mentioned in [Handle exceptions in plug-ins](handle-exceptions.md), when you write a plug-in you should try to anticipate which operations may fail and wrap them in a try-catch block. When any errors occur, you should use the <xref:Microsoft.Xrm.Sdk.InvalidPluginExecutionException> to gracefully terminate the operation with an error meaningful to the user.
40
40
41
-
A common scenario for this is when using a the [HttpClient.SendAsync Method](/dotnet/api/system.net.http.httpclient.sendasync?view=netframework-4.6.2) or [HttpClient.GetAsync Method](/dotnet/api/system.net.http.httpclient.getasync?view=netframework-4.6.2) which are asynchronous operations that returns a [Task](/dotnet/api/system.threading.tasks.task-1?view=netframework-4.6.2). To make this work in a plug-in where code needs to be synchronous, people may use the [Task<TResult>.Result Property](/dotnet/api/system.threading.tasks.task-1.result?view=netframework-4.6.2). When an error occurs, this returns an [AggregateException](/dotnet/api/system.aggregateexception?view=netframework-4.6.2) which consolidates multiple failures into a single exception which can be difficult to handle. A better design is to use [Task<TResult>.GetAwaiter()](/dotnet/api/system.threading.tasks.task-1.getawaiter?view=netframework-4.6.2).[GetResult()](/dotnet/api/system.runtime.compilerservices.taskawaiter-1.getresult?view=netframework-4.6.2) because it propagates the results as the specific error that caused the failure.
41
+
A common scenario for this is when using a the [HttpClient.SendAsync Method](/dotnet/api/system.net.http.httpclient.sendasync?view=netframework-4.6.2&preserve-view=true) or [HttpClient.GetAsync Method](/dotnet/api/system.net.http.httpclient.getasync?view=netframework-4.6.2&preserve-view=true) which are asynchronous operations that returns a [Task](/dotnet/api/system.threading.tasks.task-1?view=netframework-4.6.2&preserve-view=true). To make this work in a plug-in where code needs to be synchronous, people may use the [Task<TResult>.Result Property](/dotnet/api/system.threading.tasks.task-1.result?view=netframework-4.6.2&preserve-view=true). When an error occurs, this returns an [AggregateException](/dotnet/api/system.aggregateexception?view=netframework-4.6.2&preserve-view=true) which consolidates multiple failures into a single exception which can be difficult to handle. A better design is to use [Task<TResult>.GetAwaiter()](/dotnet/api/system.threading.tasks.task-1.getawaiter?view=netframework-4.6.2&preserve-view=true).[GetResult()](/dotnet/api/system.runtime.compilerservices.taskawaiter-1.getresult?view=netframework-4.6.2&preserve-view=true) because it propagates the results as the specific error that caused the failure.
42
42
43
-
The following example shows the correct way to manage the exception and an outbound call using [HttpClient.GetAsync Method](/dotnet/api/system.net.http.httpclient.getasync?view=netframework-4.6.2). This plug-in will attempt to get the response text for a Url set in the unsecure config for a step registered for it.
43
+
The following example shows the correct way to manage the exception and an outbound call using [HttpClient.GetAsync Method](/dotnet/api/system.net.http.httpclient.getasync?view=netframework-4.6.2&preserve-view=true). This plug-in will attempt to get the response text for a Url set in the unsecure config for a step registered for it.
44
44
45
45
```csharp
46
46
usingMicrosoft.Xrm.Sdk;
@@ -132,7 +132,7 @@ namespace ErrorRepro
132
132
133
133
This type of error occurs most frequently right after you make some change in your plug-in code. Some people use their own set of base classes to streamline their development experience. Sometimes these errors originate from changes to those base classes which a particular plug-in depends on.
134
134
135
-
For example, a recursive call without a termination condition, or a termination condition which doesn’t cover all scenarios can cause this to happen. More information: [StackOverflowException Class > Remarks](/dotnet/api/system.stackoverflowexception?view=netframework-4.6.2#remarks)
135
+
For example, a recursive call without a termination condition, or a termination condition which doesn’t cover all scenarios can cause this to happen. More information: [StackOverflowException Class > Remarks](/dotnet/api/system.stackoverflowexception?view=netframework-4.6.2&preserve-view=true#remarks)
136
136
137
137
You should review any code changes that were applied recently for the plug-in and any other code that the plug-in code depends on.
138
138
@@ -252,15 +252,14 @@ Each worker process has a finite amount of memory. There are conditions where mu
252
252
253
253
#### RetrieveMultiple with File data
254
254
255
-
The common scenario in this case is when a plug-in executes for a `RetrieveMultiple` operation where the request includes file data. For example, when retrieving email which include any file attachments. The amount of data that may be returned in a query like this is unpredictable because any email my be related to any number of file attachments and the attachments themselves can vary in size.
255
+
The common scenario in this case is when a plug-in executes for a `RetrieveMultiple` operation where the request includes file data. For example, when retrieving email which include any file attachments. The amount of data that may be returned in a query like this is unpredictable because any email my be related to any number of file attachments and the attachments themselves can vary in size.
256
256
257
257
When multiple requests of a similar nature are running concurrently, the amount of memory required becomes quite large. If it exceeds the limit the process will crash. The key to preventing this is limiting `RetrieveMultiple` queries that include entities with related file attachments. Retrieve the records using `RetrieveMultiple`, but retrieve any related files as needed using individual `Retrieve` operations.
258
258
259
259
#### Memory Leaks
260
260
261
261
A less common scenario is where the code in the plug-in is leaking memory. This can occur when the plug-in isn’t written as stateless, which is another best practice: [Develop IPlugin implementations as stateless](best-practices/business-logic/develop-iplugin-implementations-stateless.md). When the plug-in isn’t stateless and there is an attempt to continually add data to a stateful property like an array. The amount of data grows to the point where it uses all the available memory.
262
262
263
-
264
263
## Transaction errors
265
264
266
265
There are two common types of errors related to transactions:
@@ -314,8 +313,9 @@ If the plug-in is performing operations using a table or column that has been cr
314
313
In a client application you can disable commands that users are not allowed to perform. Within a plug-in you don't have this. Your code may include some automation that the calling user doesn't have the privileges to perform.
315
314
316
315
You can register the plug-in to run in the context of a user known to have the correct privileges by setting the **Run in User's Context** value to that user. Or you can execute the operation impersonating another user. More information:
317
-
-[Register a plug-in](register-plug-in.md)
318
-
-[Impersonate a user](impersonate-a-user.md)
316
+
317
+
-[Register a plug-in](register-plug-in.md)
318
+
-[Impersonate a user](impersonate-a-user.md)
319
319
320
320
<!-- But if you prefer that the logic in your plug-in adapt to the privileges that the calling user has, you really need to verify the user's privileges in your code.-->
321
321
@@ -364,7 +364,7 @@ At run-time the error is frequently due to the developer assuming that the value
364
364
365
365
### Prevention
366
366
367
-
To prevent this error you must check that the key exists before attempting to use it to access a value.
367
+
To prevent this error you must check that the key exists before attempting to use it to access a value.
368
368
369
369
For example, when accessing a table column, you can use the <xref:Microsoft.Xrm.Sdk.Entity>.<xref:Microsoft.Xrm.Sdk.Entity.Contains(System.String)> method to check whether a column exists in a table as shown in the following code.
This .NET 6.0 sample demonstrates how to perform parallel data operations using the Dataverse Web API.
23
22
24
23
This sample uses the common helper code in the [WebAPIService class library (C#)](webapiservice.md).
@@ -62,7 +61,7 @@ To encounter service protection limits with this sample you should raise the `nu
62
61
63
62
This example uses the [Parallel.ForEachAsync Method](/dotnet/api/system.threading.tasks.parallel.foreachasync) introduced with .NET 6.0.
64
63
65
-
This sample processes a list of requests to create account records, sending the requests in parallel and then uses the data returned to add requests to delete the created accounts to a [ConcurrentBag](/dotnet/api/system.collections.concurrent.concurrentbag-1?view=net-6.0). After the records are created, the number of seconds to create the records is displayed.
64
+
This sample processes a list of requests to create account records, sending the requests in parallel and then uses the data returned to add requests to delete the created accounts to a [ConcurrentBag](/dotnet/api/system.collections.concurrent.concurrentbag-1?view=net-6.0&preserve-view=true). After the records are created, the number of seconds to create the records is displayed.
66
65
67
66
Then, the delete requests in the `ConcurrentBag` are processed and the time spent deleting the records is displayed.
0 commit comments