Click here to Skip to main content
15,903,362 members
Articles / Programming Languages / C#

Dynamic jQuery DataTable Integration (Columns & Records)

Rate me:
Please Sign up or sign in to vote.
1.44/5 (2 votes)
28 Jun 2018CPOL 2.2K   1   1  
JQuery Datatable (Dynamic columns) populate after ajax json response via processing of EF Raw Sql query

Introduction

Most of cases we must develop many pages in project with different module/entity. Personally, experience after long time engage with financial /non-financial/corporate industries. There are several pages where we need to use data table/grid. Each page has similarities except columns/table header and respective rows/records.Using following architecture only require supplying raw native sql and it will show grid with data.

Following architecture will able to handle dynamic columns and respective rows. So, I have tried to make dynamic Jquery Datatable which populate grid basis on return json result.

Requirment

1. CLIENT SIDE: jQuery DataTables should able to display dynamic column and respective records.

2. SERVER SIDE: Entity Framework (Code First Approach) should able to execute Raw Sql Query.

Procedure/Steps

Steps : 1. Install Entity Framework using NuGet command Install-Package EntityFramework

Steps : 2. Set Connection string for your database in Web.Config

Steps : 3. Enable Migration for Code First Approach

I have taken multiple tables for generate separate sql native/raw sql query.

ScientistData and InventionData are Entity/tables for sample illustration 

C#
public class ScientistData
   {
       public int Id { get; set; }
       public string Name { get; set; }
       public string Duration { get; set; }
       public string Description { get; set; }
   }
   public class InventionData
   {
       public int Id { get; set; }
       public string Inventor { get; set; }
       public string Invention { get; set; }
   }

Prepare for context for database table migration

C#
public class QueryContext : DbContext
    {
        public QueryContext() : base("name=QueryManager") { }
        public DbSet<ScientistData> ScientistData { get; set; }
        public DbSet<InventionData> InventionData { get; set; }
    }
Trigger NuGet Command for Enable Migration as well Table creation
I have taken multiple tables for generate separate sql native/raw sql query.
  1. Enable-Migrations
  2. Add-Migration IntialCreate
  3. Update-Database

Finally, it creates database as well tables.

Steps : 4. Create custom extension method which supports to execute raw native sql query.

(Source : https://stackoverflow.com/questions/26749429/anonymous-type-result-from-sql-query-execution-entityframework/26749784#)

C#
 public static class DynamicQueryBuilder
    {
        public static IEnumerable DynamicSqlQuery(this Database database, string sql, params object[] parameters)
        {
            TypeBuilder builder = createTypeBuilder(
                    "MyDynamicAssembly", "MyDynamicModule", "MyDynamicType");
            using (System.Data.IDbCommand command = database.Connection.CreateCommand())
            {
                try
                {
                    database.Connection.Open();
                    command.CommandText = sql;
                    command.CommandTimeout = command.Connection.ConnectionTimeout;
                    foreach (var param in parameters)
                    {
                        command.Parameters.Add(param);
                    }

                    using (System.Data.IDataReader reader = command.ExecuteReader())
                    {
                        var schema = reader.GetSchemaTable();

                        foreach (System.Data.DataRow row in schema.Rows)
                        {
                            string name = (string)row["ColumnName"];
                            //var a=row.ItemArray.Select(d=>d.)
                            Type type = (Type)row["DataType"];
                            if (type != typeof(string) && (bool)row.ItemArray[schema.Columns.IndexOf("AllowDbNull")])
                            {
                                type = typeof(Nullable<>).MakeGenericType(type);
                            }
                            createAutoImplementedProperty(builder, name, type);
                        }
                    }
                }
                finally
                {
                    database.Connection.Close();
                    command.Parameters.Clear();
                }
            }

            Type resultType = builder.CreateType();

            return database.SqlQuery(resultType, sql, parameters);
        }

        private static TypeBuilder createTypeBuilder(
            string assemblyName, string moduleName, string typeName)
        {
            TypeBuilder typeBuilder = AppDomain
                .CurrentDomain
                .DefineDynamicAssembly(new AssemblyName(assemblyName),
                                       AssemblyBuilderAccess.Run)
                .DefineDynamicModule(moduleName)
                .DefineType(typeName, TypeAttributes.Public);
            typeBuilder.DefineDefaultConstructor(MethodAttributes.Public);
            return typeBuilder;
        }

        private static void createAutoImplementedProperty(
            TypeBuilder builder, string propertyName, Type propertyType)
        {
            const string PrivateFieldPrefix = "m_";
            const string GetterPrefix = "get_";
            const string SetterPrefix = "set_";

            // Generate the field.
            FieldBuilder fieldBuilder = builder.DefineField(
                string.Concat(PrivateFieldPrefix, propertyName),
                              propertyType, FieldAttributes.Private);

            // Generate the property
            PropertyBuilder propertyBuilder = builder.DefineProperty(
                propertyName, System.Reflection.PropertyAttributes.HasDefault, propertyType, null);

            // Property getter and setter attributes.
            MethodAttributes propertyMethodAttributes =
                MethodAttributes.Public | MethodAttributes.SpecialName |
                MethodAttributes.HideBySig;

            // Define the getter method.
            MethodBuilder getterMethod = builder.DefineMethod(
                string.Concat(GetterPrefix, propertyName),
                propertyMethodAttributes, propertyType, Type.EmptyTypes);

            // Emit the IL code.
            // ldarg.0
            // ldfld,_field
            // ret
            ILGenerator getterILCode = getterMethod.GetILGenerator();
            getterILCode.Emit(OpCodes.Ldarg_0);
            getterILCode.Emit(OpCodes.Ldfld, fieldBuilder);
            getterILCode.Emit(OpCodes.Ret);

            // Define the setter method.
            MethodBuilder setterMethod = builder.DefineMethod(
                string.Concat(SetterPrefix, propertyName),
                propertyMethodAttributes, null, new Type[] { propertyType });

            // Emit the IL code.
            // ldarg.0
            // ldarg.1
            // stfld,_field
            // ret
            ILGenerator setterILCode = setterMethod.GetILGenerator();
            setterILCode.Emit(OpCodes.Ldarg_0);
            setterILCode.Emit(OpCodes.Ldarg_1);
            setterILCode.Emit(OpCodes.Stfld, fieldBuilder);
            setterILCode.Emit(OpCodes.Ret);

            propertyBuilder.SetGetMethod(getterMethod);
            propertyBuilder.SetSetMethod(setterMethod);
        }
    }
 
Steps : 5. Prepare helper method which will returns results from database operations.
Following sql query which returns all columns values as followings:
C#
//Essential to execute Raw Sql Query
 public object ExecuteRawSql(string Query)
 {
     return this.Database.DynamicSqlQuery(Query);
 }
 //Helpful to return all Table object from Database. Essential to make intellisense for Query Builder
 public List<string> TableObject()
 {
     return this.Database.SqlQuery<string>("SELECT TABLE_SCHEMA+'.'+ TABLE_NAME as TableObject FROM INFORMATION_SCHEMA.TABLES order by TABLE_NAME").ToList();
 }
ExecuteRawSql Custom extension methods which return type is object which is not support current entity framework.
 
Step 6: Setup jQuery Datatable as following basics structure :
Note: It is highly recommended to handle table header based on json result after ajax response.
 
JavaScript
var GenerateQuery = function () {
        $("#resultContainer").css("display", "none");        
        var Payload = { 'Type': $("#Type").val(), 'Query': $("#Query").val() };
        $.ajax({
            url: '/QueryManager/GenerateResult',
            type: 'POST',
            data: Payload,
            success: function (response) {
                if (response.status != true) {
                    console.log("Exception", response);
                    alert('There is some error has occured!. Please see in console for details of error');
                }
                else {
                    $("#resultContainer").css("display", "block");
                    //Handlaling JQuery Datatable Dynamically...
                    //Check Data Table has if already initilialize then need to destroy first!
                    if ($.fn.DataTable.isDataTable('#example')) {
                        $('#example').DataTable().destroy();
                        $('#example').empty();
                    }
                    //Listing Columns (Table Header) from json ajax response
                    var Columns = [];
                    var TableHeader = "<thead><tr>";
                    $.each(response.result[0], function (key, value) {
                        Columns.push({ "data": key })
                        TableHeader += "<th>" + key + "</th>"
                    });
                    TableHeader += "</thead></tr>";
                    $("#example").append(TableHeader);
                    $('#example').dataTable({
                        "oLanguage": {
                            "sLengthMenu": "_MENU_ &nbsp;"
                        },
                        "data": response.result,
                        "columns": Columns,
                        "JQueryUI": true,
                        dom: 'Bfrtip',
                        dom: 'lBfrtip',
                    });                    
                    
                }
            }
        });
    }
 
Need to call ajax request with supplied dynamic raw sql query and server will response data/result accordingly.
  1. Prepare table header basis on json result of ajax response.
  2. Destory or un initialize the jquery datatable if already initialized table. 
  3. Initialize jquery datatable with ajax response

Result/Output: You can write Raw Sql Query and Execute it!

Points of Interest

  • Main challenges, I have found while binding dynamic json result to jquery datatable, need to create table header using script.
  • There is no dynamic return type supporting in Entity Framework (Version 6.0.0.0) right now, so need to build dynamic executable custome extention method.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Team Leader Nebula Infraspace LLP
India India
Having 6+ year experience on Microsoft .Net/Programming

Object oriented programming
.Net Framework Architecture
Console Programming / Dynamic or Runtime Program Execution
Multi Threaded Programming
Windows Application Programming
RegEx
TCP/IP Communication
Http Protocol and REST API Architecture
Socket Programing
SMS, Email, Domain Registration API Integration
PayPal, Authorize.Net Payment Gateway
EntityFramework, Linq & Lamda Expression
JavaScript, Ajax and Jquery
Asp.net Web Applications
MVC Razor View Engine Framework
NopCommerce Customization, InfusionSoft Integration
Azure Web App, Salesforce and Amazon Web Services
Azure Media Services
Media Player Integration and Encryption on Streaming Framegments
Microsoft Sql Server Database

Comments and Discussions

Discussions on this specific version of this article. Add your comments on how to improve this article here. These comments will not be visible on the final published version of this article.
 
-- There are no messages in this forum --