Blog

Tagged by 'crud'

  • To continue my ever expanding Salesforce journey in the .NET world, I am adding some more features to my "ObjectDetailInfoProvider" class that I started writing in my previous post. This time making some nice easy, re-usable CRU(D) methods... just without the delete.

    All the methods query Salesforce using Force.com Toolkit for .NET, which I have slightly adapted to allow me to easily interchange to a traditional REST approach when required.

    Get Data

    /// <summary>
    /// Gets data from an object based on specified fields and conditions.
    /// </summary>
    /// <param name="objectName"></param>
    /// <param name="fields"></param>
    /// <param name="whereCondition"></param>
    /// <param name="orderBy"></param>
    /// <param name="max"></param>
    /// <returns></returns>
    public static async Task<List<dynamic>> GetRows(string objectName, List<string> fields, string whereCondition, string orderBy = null, int max = -1)
    {
        ForceClient client = await AuthenticationResponse.ForceCom();
    
        #region Construct SQL Query
    
        StringBuilder query = new StringBuilder();
    
        query.Append("SELECT ");
    
        if (fields != null && fields.Any())
        {
            for (int c = 0; c <= fields.Count - 1; c++)
            {
                query.Append(fields[c]);
    
                query.Append(c != fields.Count - 1 ? ", " : " ");
            }
        }
        else
        {
            query.Append("* ");
        }
    
        query.Append($"FROM {objectName} ");
    
        if (!string.IsNullOrEmpty(whereCondition))
            query.Append($"WHERE {whereCondition} ");
    
        if (!string.IsNullOrEmpty(orderBy))
            query.Append($"ORDER BY {orderBy}");
    
        if (max > 0)
            query.Append($" LIMIT {max}");
    
        #endregion
    
        // Pass SQL query to Salesforce.
        QueryResult<dynamic> results = await client.QueryAsync<dynamic>(query.ToString());
    
        return results.Records;
    }
    

    Insert Row

    /// <summary>
    /// Creates a new row within an specific object.
    /// </summary>
    /// <param name="objectName"></param>
    /// <param name="fields"></param>
    /// <returns>Record ID</returns>
    public static async Task<string> InsertRow(string objectName, Dictionary<string, object> fields)
    {
        try
        {
            ForceClient client = await AuthenticationResponse.ForceCom();
    
            IDictionary<string, object> objectFields = new ExpandoObject();
    
            // Iterate through fields and populate dynamic object.
            foreach (KeyValuePair<string, object> f in fields)
                objectFields.Add(f.Key, f.Value);
    
            SuccessResponse response = await client.CreateAsync(objectName, objectFields);
    
            if (response.Success)
                return response.Id;
            else
                return string.Empty;
        }
        catch (Exception ex)
        {
            // Log error here.
    
            return string.Empty;
        }
    }
    

    Update Row

    /// <summary>
    /// Updates existing row within an specific object.
    /// </summary>
    /// <param name="recordId"></param>
    /// <param name="objectName"></param>
    /// <param name="fields"></param>
    /// <returns>Record ID</returns>
    public static async Task<string> UpdateRow(string recordId, string objectName, Dictionary<string, object> fields)
    {
        try
        {
            ForceClient client = await AuthenticationResponse.ForceCom();
    
            IDictionary<string, object> objectFields = new ExpandoObject();
    
            // Iterate through fields and populate dynamic object.
            foreach (KeyValuePair<string, object> f in fields)
                objectFields.Add(f.Key, f.Value);
    
            SuccessResponse response = await client.UpdateAsync(objectName, recordId, objectFields);
    
            if (response.Success)
                return response.Id;
            else
                return string.Empty;
        }
        catch (Exception ex)
        {
            // Log error here.
    
            return string.Empty;
        }
    }
    

    The neat thing about Insert and Update methods is that I am using an ExpandoObject, which is a dynamic data type that can represent dynamically changing data. This is a new feature in .NET 4.0. Ideal for the ultimate flexibility when it comes to parsing field name and its value. It's a very dynamic object that allows you to add properties and methods on the fly and then access them again.

    If there is any other useful functionality to add to these methods, please leave a comment.