Showing posts with label .NET. Show all posts
Showing posts with label .NET. Show all posts

Tuesday, April 16, 2019

I'm a huge fan of detailed application logs

By Steve Endow

This week, one of my customers suddenly started having severe performance issues with a custom Dynamics GP web API that I developed for them a few years ago.

The customer and their Dynamics GP partner immediately knew about the performance problem because the web API has logic to detect certain performance issues, log the problem, and proactively send an email notification to the customer and GP partner.

This is a sample of the log file that told me everything I needed to know to work on diagnosing the issue.

Full Time Debug Level Logging with Elapsed Time Measurement

Notice that the elapsed time (in parens) jumps from 0.09 seconds to 32.96 seconds when the GetCCCustomerProfileID step completes?  That step normally takes a few milliseconds, but was suddenly taking 20-40 seconds to complete.  No bueno.  That step calls an on-premises web service for a credit card management system, and that system was experiencing a problem.  Fortunately, my code is setup to log a warning and send an email whenever an operation takes more than 20 seconds, so admins were notified as soon as the problem started.

Thursday, March 7, 2019

C# SqlException: Procedure or function has too many arguments specified

By Steve Endow

I've been fighting this error for years in my Data Access class. Only yesterday did I figure out the cause.

It's related to the design of my Data Access class, and specific cases where I need to make multiple calls to the database in a single method.

This is the error:

SqlException: Procedure or function has too many arguments specified

This is an example of a stored procedure call that leads up to the error.

Assembling SQL Parameters for a Stored Procedure

Sunday, February 17, 2019

3 Fun Stories About Strings and C#

By Steve Endow

Whenever you work with data, an integration, or code, you will invariably work with strings. Usually lots of strings.

In some cases, every data field you work with will be a string. In other cases, you'll need to convert strings to numbers, dollars, or dates.  And sometimes you'll need to format strings, whether composing data into XML, formatting social security numbers, or working with different date formats.

In this video, I share 3 stories about working with strings in C# that I encountered recently on projects.




Thursday, December 20, 2018

Bulk Export Dynamics GP Document Attachments using .NET

By Steve Endow

2/20/2023 UPDATE:  Version 1.30 released


A user on the GPUG Open Forum asked if there was a way to export all of the documents that are attached to Dynamics GP customers.

I previously wrote a blog posts showing how to export a single document attachment using BCP:

https://dynamicsgpland.blogspot.com/2017/05/extract-dynamics-gp-document-attach.html


And another showing how to export a single document attachment using .NET:

https://dynamicsgpland.blogspot.com/2017/05/extract-and-save-dynamics-gp-document.html


But the BCP solution is only for a single attachment, and the .NET solution didn't have any features for filtering or organized export of attachments.

So today I updated the .NET solution to allow the user to select a Database, Record Type, and indicate whether Deleted attachments should be exported.



Once those options are selected, the user can retrieve a list of all of the attachments, which shows the type, the associated record number, the file name, and file size.

The user can then select an export path and click a button to export all of the attachments to disk.


The application and full source code can be downloaded here:

       Version 1.30:  Precipio SaveDocAttachFiles v1.30.zip


Version 1.30 adds support for the EFOQUS SharePoint Connector for Business Central

-Save files as  <Attachment Name>!<BC Table Num>!<Record ID>

-Save files as  <Attachment Name>!<BC Table Num>!<BC Record Type Num><Record ID>


New record types can be added by editing the SaveDocAttachFiles.exe.config file. Locate the RecordTypes setting at the bottom of the file and add new name + code pairs to the list.


Please note that this .NET application was assembled in a few hours, and is not a refined, polished, commercial software release.  It does not have lots of configuration options or error handling, so you will want to test it in a TEST environment and be aware that it may need some modifications to work in your environment.


Steve Endow is a Microsoft MVP in Los Angeles.  He is the owner of Precipio Services, which provides Dynamics GP integrations, customizations, and automation solutions.

You can also find him on Twitter and YouTube





Friday, November 30, 2018

eConnect Performance: Using GetNextDocNumbers vs taGetNext stored procedures

By Steve Endow

This one is definitely an obscure topic that nobody is asking about.

But hey, I was curious.

I was researching whether the eConnect GetNextGLJournalEntryNumber could handle a heavy load, and whether it would throw any errors when issuing lots of JE numbers.

Interestingly, I was unable to break it.  I was able to get one SQL exception error when running my test while also trying to get a new JE number in the GP Journal Entry window, but I was unable to reproduce that error.

This image shows 3 instances of my load test application simultaneously retrieving a total of 3,000 JE numbers over about 45 seconds.

3,000 JE Numbers


 public string GetNextJENumbereConn()  
 {  
   GetNextDocNumbers getNext = new GetNextDocNumbers();  
   
   try  
   {  
     string nextJE = getNext.GetNextGLJournalEntryNumber(IncrementDecrement.Increment, ConnectionStringWindows());  
     return nextJE;  
   }  
   catch (Exception ex)  
   {  
     throw ex;  
   }  
 }  


Testing just 1 instance of my load tester, I saw that it took about 16 seconds to generate 1,000 JE numbers using the eConnect method.

So, naturally, I wondered what the performance would be if I called the stored procedure directly.

Thursday, November 29, 2018

How long does it take to import Dynamics GP GL JEs with Analytical Accounting?

By Steve Endow

I recently did some tests to see how long it takes to import GL Journal Entries with large numbers of line items.

Those test results were fairly consistent, and showed that eConnect does a pretty good job of importing JEs with a large number of lines.  Only 8 seconds to import a JE with 2,000 lines seems pretty good to me, as I suspect most customers don't import JEs that large.

For anyone who is familiar with Dynamics GP integrations, the next obvious question is how eConnect handles imports of GL JEs when there is Analytical Accounting data involved.

From experience, I know that GL JEs with AA do not import terribly quickly or efficiently.

Here are the results of importing a single JE with varying line counts.  Every line in the JE has one AA code assigned.

100 lines:  3-8 seconds
200 lines:  3-9 seconds
500 lines:  9-17 seconds
1,000 lines:  21-47 seconds 
2,000 lines:  174-222 seconds


There are two obvious differences when you add Analytical Accounting codes to your GL JE import.

First, they take much, much longer.  A standard JE with 500 lines takes 2 seconds, but when you add AA, that same JE takes 9-17 seconds.

A standard JE with 2,000 lines takes 8 seconds, but when you add AA, that same JE takes 174-222 seconds.

HUUUUUGE decrease in import performance.

The second issue is the incredible variance in import times for the single JEs with AA data.  When importing the standard JEs, the import times were completely consistent.  Over 10 runs, I might have seen a 1 second variance, if any.

In this test with AA data, I imported the same JE at least 10 times for each line count, and you can see how different the times are.  The durations seem almost random.  The import times did not gradually increase or decrease--they would just increase on one run, and then decrease on the next.

The times varied from 89% to 200%, which is pretty wild.  I don't know how a stored procedure could have so much variance in performance from one run to the next.  If it wasn't such a nightmare to trace the activity from the eConnect procedures, I'd look into it.

So there you have it.  If you have to import transactions with Analytical Accounting data, you have been warned.  It seems that the eConnect procs for AA do not perform well.

Steve Endow is a Microsoft MVP in Los Angeles.  He is the owner of Precipio Services, which provides Dynamics GP integrations, customizations, and automation solutions.

You can also find him on Twitter and YouTube





Thursday, November 15, 2018

.NET code to create a Dynamics GP batch with eConnect

By Steve Endow

I just posted a story about how I discovered that sometimes I need to explicitly create Dynamics GP batches using eConnect in order to control the batch posting date.

Here's the code that I used.

First, I check to see if the batch exists.


 public static bool BatchExists(string database, int series, string batchSource, string batchID)   
 {  
   try  
   {  
     string commandText = "SELECT COUNT(*) AS RecordCount FROM dbo.SY00500 WHERE SERIES = @SERIES AND BCHSOURC = @BCHSOURC AND BACHNUMB = @BACHNUMB"; // AND GLPOSTDT = @GLPOSTDT";  
     SqlParameter[] sqlParameters = new SqlParameter[3];  
     sqlParameters[0] = new SqlParameter("@SERIES", System.Data.SqlDbType.Int);  
     sqlParameters[0].Value = series;  
     sqlParameters[1] = new SqlParameter("@BCHSOURC", System.Data.SqlDbType.VarChar, 15);  
     sqlParameters[1].Value = batchSource.Trim();  
     sqlParameters[2] = new SqlParameter("@BACHNUMB", System.Data.SqlDbType.VarChar, 15);  
     sqlParameters[2].Value = batchID.Trim();  
     string result = DataAccess.ExecuteScalar(database, CommandType.Text, commandText, sqlParameters);  
     int recordCount = Convert.ToInt32(result);  
     if (recordCount > 0)  
     {  
       return true;  
     }  
     else  
     {  
       return false;  
     }  
   }  
   catch (Exception ex)  
   {  
     Log.Write("An unexpected error occurred in DataAccess.BatchExists: " + ex.Message, true);  
     return false;  
   }  
 }  


If the batch does exist, I make sure to update the posting date.

Sometimes you have to explicitly create Dynamics GP Batches with eConnect

By Steve Endow

You just can't know everything.

Maybe I never took the time to look at this one field when using that particular Dynamics GP batch posting setting, and never knew about this quirk.

Maybe I did know about this quirk at some point over the last 12 or 13 years working with eConnect, but forgot about it.

Either way, I didn't know about it when I needed to know about it.

Last week I had a call with a customer to try and troubleshoot a weird posting date issue.  They import a bunch of AP Invoices every Monday morning into dozens of batches, review the batch that Monday or Tuesday, and then post the batch.  Simple, right?

But when they were reconciling the GL for their month end close, they were seeing AP Invoice transactions post to prior weeks and prior fiscal periods.  An invoice imported on November 5 posted to October 30.  Another invoice imported on November 5 posted to November 1.

It was weird.

We looked at their GP posting settings for Payables Transaction Entry, and it looked pretty normal.

Typical Batch Posting Date

The customer is using the Posting Date from the Batch.  Okay, so that rules out an issue with the invoices posting based on the Transaction posting date.

But, that doesn't explain why invoices imported at the same time on Monday morning would post to different dates.

How many digits can a Business Central Amount field actually support?

 by Steve Endow (If anyone has a technical explanation for the discrepancy between the Docs and the BC behavior, let me know!) On Sunday nig...