function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
LB_DDLB_DD 

API Performance extremely slow (first connection)

Hello,

 

I use VS2010, .NET 3.5 to create a website that connect with Salesforce. When I access the website, exist a Query to show some information, the time to show this information is a lot! about 15s to 25s, but if I call se same page the performance is better (5s).

 

In general the performance is slow (I think), can anyone have same problem and resolve?

 

I put my code here to help understand whats happen!

 

ForceConnection.cs

using System;
using System.Collections.Generic;
using System.Web;
using SalesforceCore.SFAPIenterprise;

namespace DD.Salesforce
{
    public class ForceConnection
    {
        public string SessionID { get; set; }
        public string ServerUrl { get; set; }

        public ForceConnection(string connectionString)
        {
            ForceConnectionStringBuilder connectionBuilder = 
                new ForceConnectionStringBuilder(connectionString);

            Login(connectionBuilder.Username, connectionBuilder.Password, connectionBuilder.Token);
        }

        public ForceConnection(string username, string password, string securityToken)
        {
            Login(username, password, securityToken);
        }

        private bool Login(string username, string password, string securityToken)
        {
            try
            {
                using (SforceService service = new SforceService())
                {
                    LoginResult loginResult = 
                        service.login(username, String.Concat(password, securityToken));

                    this.SessionID = loginResult.sessionId;
                    this.ServerUrl = loginResult.serverUrl;
                }

                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }
    }
}

 

 

ForceConnectionStringBuilder.cs

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Web;
using SalesforceCore.SFAPIenterprise;

namespace DD.Salesforce
{
    public class ForceConnectionStringBuilder
    {
        public string Username { get; set; }
        public string Password { get; set; }
        public string Token { get; set; }

        public string ConnectionString
        {
            get 
            { 
                return String.Format("Username={0}; Password={1}; Token={2};"); 
            }
            set 
            {
                string[] pairs = value.Split(';');

                foreach (string pair in pairs)
                {
                    if (String.IsNullOrEmpty(pair))
                        continue;

                    string[] parts = pair.Split('=');

                    if (parts.Length != 2)
                    {
                        throw new ApplicationException("Malformed connection string parameter.  The connection string should be formated list this: username=value1; password=value2; token=value3;");
                    }

                    string key = parts[0].Trim();
                    string setting = parts[1].Trim();

                    if (String.IsNullOrEmpty(key) || String.IsNullOrEmpty(setting))
                        continue;

                    switch(key.ToLower())
                    {
                        case "username":
                            Username = setting;
                            break;
                        case "password":
                            Password = setting;
                            break;
                        case "token":
                            Token = setting;
                            break;
                        default :
                            throw new ApplicationException(String.Format("Invalid parameter {0}", parts[0]));
                    }
                }
            }
        }
        
        public ForceConnectionStringBuilder()
        {

        }

        public ForceConnectionStringBuilder(string connectionString)
        {
            ConnectionStringSettings settings = ConfigurationManager.ConnectionStrings[connectionString];
            if (settings != null)
            {
                ConnectionString = settings.ConnectionString;
            }
            else
            {
                ConnectionString = connectionString;
            }
        }
    }
}

 

 

ApiService.cs

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Web;
using SalesforceCore.SFAPIenterprise;

namespace DD.Salesforce
{
    public class ApiService : IDisposable
    {
        public static Dictionary<Guid, List<sObject>> asyncResults;

        private SforceService salesforceService;
        const int defaultTimeout = 60000;

        public ApiService()
        {
            salesforceService = new SforceService();
            salesforceService.Timeout = defaultTimeout;
            asyncResults = new Dictionary<Guid, List<sObject>>();
        }

        public ApiService(int timeout) : this()
        {
            salesforceService.Timeout = timeout;
        }

        public List<T> Query<T>(string soql) where T : sObject, new()
        {
            List<T> returnList = new List<T>();

            SetupService();
            QueryResult results = new QueryResult();
            try
            {
                results = salesforceService.query(soql);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message.ToString());
            }

            for (int i = 0; i < results.size; i++)
            {
                T item = results.records[i] as T;

                if (item != null)
                    returnList.Add(item);
            }
            
            return returnList;
        }

        public T QuerySingle<T>(string soql) where T : sObject, new()
        {
            T returnValue = new T();

            SetupService();            

                QueryResult results = salesforceService.query(soql);

                if (results.size == 1)
                    returnValue = results.records[0] as T;
            
            return returnValue;
        }

        public Guid QueryAsync(string soql)
        {
            SetupService();
            salesforceService.queryCompleted += salesforceService_queryCompleted;
            
            Guid id = Guid.NewGuid();
            
            salesforceService.queryAsync(soql, id);

            return id;
        }

        void salesforceService_queryCompleted(object sender, queryCompletedEventArgs e)
        {
            Guid id = (Guid)e.UserState;
            List<sObject> results = e.Result.records.ToList();

            if (asyncResults.ContainsKey(id))
                asyncResults[id].AddRange(results);
            else
                asyncResults.Add((Guid)e.UserState, results);
        }

        public SaveResult[] Update(sObject[] items)
        {
            SetupService();

            return salesforceService.update(items);
        }

        public UpsertResult[] Upsert(string externalID, sObject[] items)
        {
            SetupService();

            return salesforceService.upsert(externalID, items);
        }

        public SaveResult[] Insert(sObject[] items)
        {
            SetupService();

            return salesforceService.create(items);
        }

        public DeleteResult[] Delete(string[] ids)
        {
            SetupService();

            return salesforceService.delete(ids);
        }

        public UndeleteResult[] Undelete(string[] ids)
        {
            SetupService();

            return salesforceService.undelete(ids);
        }

        private void SetupService()
        {
            ForceConnection connection = new ForceConnection("SalesforceLogin");
            salesforceService.SessionHeaderValue =
                new SessionHeader() { sessionId = connection.SessionID };
            try
            {
                salesforceService.Url = connection.ServerUrl;                
            }
            catch (Exception ex)
            {
                throw new Exception("Salesforce Authentication Fail! Please verify: Username, Password and Token.");             
            }            
        }

        public void  Dispose()
        {
            salesforceService.Dispose();
        }

        public static string ToIsoFormat(DateTime dateTime)
        {
            return dateTime.ToString("yyyy-MM-ddTHH:mm:ssZ");
        }
        public static string ToIsoDateFormat(DateTime dateTime)
        {
            return dateTime.ToString("yyyy-MM-dd");
        }
    }
}

 

myControllerTests.cs

using System;
using System.Collections.Generic;
using System.Web;
using SalesforceCore.SFAPIenterprise;
using System.Data;
using DD.Salesforce
namespace DD.Controllers
{
    /// <summary>
    /// Controller to access object on Salesforce.com
    /// </summary>
    public class ControllerTestes
    {
        public List<Teste__c> List()
        {
            string soql =
               @"Select s.Id, s.Name, s.Field1__c, s.Field2__c, s.Field3__c from Teste__c s";

            using (ApiService api = new ApiService())
            {
                List<Teste__c> Testes = api.Query<Teste__c>(soql);
                return Testes;
            }
        }

        public Teste__c Select(string id)
        {
            string soql =
               String.Format(@"Select s.Id, s.Name, s.Field1__c, s.Field2__c, s.Field3__c from Teste__c s WHERE s.Id = '{0}'", id);

            using (ApiService api = new ApiService())
            {
                Teste__c Testes = api.QuerySingle<Teste__c>(soql);

                return Testes;
            }
        }

        public SaveResult[] Add(string[] DadosTeste)
        {
            SaveResult[] result;
            Teste__c aTeste = 
                new Teste__c() { 
                    Field1__c = DadosTeste[0],
                    Field2__c = DadosTeste[1],
                    Field3__c = Convert.ToDouble(DadosTeste[2]),
                    Field3__cSpecified = true
                };
            using (ApiService api = new ApiService())
            {
                sObject[] adds = new sObject[] { aTeste };
                result = api.Insert(adds);
            }
            return result;
        }

        public DeleteResult[] Delete(string[] TesteID)
        {
            DeleteResult[] result;
            using (ApiService api = new ApiService())
            {
                result = api.Delete(TesteID);
            }
            return result;
        }
        //-- Don't know how create Async calls!!!!
        public void ListAsync()
        {
        }
    }
}

 

Default.aspx:

using System;
using System.Data;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using SalesforceCore.SFAPIenterprise;
using DD.Controllers;


namespace myProjectTest
{
    public partial class getData : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
               string myID = "";
                try{
                   myID = Request.Params["id"].ToString();
                }catch{}
                
                myLabel.Text = getTheData(myID));

        }

        protected string getTheData(string recordid)
        {            
            string res = "";
            if (recordid.Length>0){
             ControllerTestes test = new ControllerTestes();
             Teste__c dsTest = new Teste__c();             
             dsTest = test.Select(recordid);
             if (dsTest != null)
             {
                try
                {
                    res = dsTest.Field1__c.ToString()+" / "+dsTest.Field2__c.ToString()+" / "+dsTest.Field2__c.ToString();
                }
                catch { }
            }
            }else{
              res = "No ID supplied!";
            }
            return res;
        }
       
    }
}

 

 

This is a simple request (Query), but with 100 or more records (using a List)  the performance is poor.

 

I don't know how make Async request (query's) to Salesforce or if exist a better code to make call to Salesforce API!

 

Anyone can help me to speed up the call to Salesforce?

 

Thanks in advance.

 

Best Regards,

LB

 


 

 

SuperfellSuperfell

One thing is that .NET will code gen all the xml serialization/deserialization code from all the anotations on first access, Especially if you're uisng the enterprise WSDL, this can be a significant hit. There are options to have these classes generated as part of your build, rather than as a runtime generation, which can speed things up significantly on the first hit.