Извлечение подмножества столбцов с данными в C # и последующая отправка их клиенту браузера в виде строки JSON

#sql-server #json #c#-4.0 #datetime #system.data.datatable

#sql-сервер #json #c #-4.0 #datetime #system.data.datatable

Вопрос:

Вот сценарий: веб-сервис среднего уровня C # содержит данные, отправленные с SQL Server, в объекте System.Data.DataTable. В коллекции столбцов DataTable есть десятки столбцов. Клиенту браузера нужно просмотреть только около шести из них. Хранимая процедура на сервере общего назначения, не предназначена для этой конкретной задачи. Предположим, что мы должны использовать его, а не писать новый SP.

Есть ли простой способ, возможно, с использованием generics, извлечь нужное подмножество столбцов из этого DataTable в список или коллекцию, а затем преобразовать полученный список или коллекцию в JSON с помощью JSON.NET ?

Возможно ли создать скелетное определение класса C # foo с соответствующими именами полей (и типами данных), а затем сопоставить эти имена полей «автоматически» и тем самым сгенерировать a List<foo> из коллекции строк DataTable?

В идеале, во время преобразования JSON любые значения даты и времени SQL Server (например 2014-06-24T18:45:00 , ) будут преобразованы в значение, которое упростит создание экземпляра даты javascript в клиенте без необходимости выполнять строковые манипуляции с представлением даты.

Ответ №1:

Полный рабочий код консольного приложения вставлен ниже. Но 2 основных метода, которые вам нужны, заключаются в следующем.

Чтобы этот код заработал, вам нужно будет выполнить следующие действия в вашем проекте.

  1. Добавьте JSON.Net пакет Nuget в проект.
  2. Добавьте ссылку на System.Web.Extensions (если вы получаете ошибку компиляции в строке, на которую System.Web.Script.Serialization.JavaScriptSerializer ссылается GetJson метод.
     /// <summary>
    /// Returns Json representation of Generic class with only matching properties from the DataTable (passed as parameter)
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="dt"></param>
    /// <returns></returns>
    public static string GetJsonFromDataTable<T>(DataTable dt) where T : new()
    {
        string json = GetJson(dt);
        return JsonConvert.SerializeObject(JsonConvert.DeserializeObject<List<T>>(json));
    }
    
    /// <summary>
    /// Returns a JSON string for entire DataTable (passed as parameter)
    /// </summary>
    /// <param name="dt"></param>
    /// <returns></returns>
    public static string GetJson(DataTable dt)
    {
        System.Web.Script.Serialization.JavaScriptSerializer serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
        List<Dictionary<string, object>> rows = (from DataRow dr in dt.Rows select dt.Columns.Cast<DataColumn>().ToDictionary(col => col.ColumnName.Trim(), col => dr[col])).ToList();
        return serializer.Serialize(rows);
    }
     

Полностью рабочий код консольного приложения.

Создайте новое консольное приложение и замените все в Program.cs нем этим кодом. Также добавьте JSON.Подключитесь к проекту консольного приложения и добавьте ссылки на System.Web.Extensions него .

 namespace DataTable2Json
{
    using Newtonsoft.Json;
    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Linq;

    public class Patient
    {
        public string FullName { get; set; }
        public string PatientID { get; set; }
        public int NumberOfIllnesses { get; set; }
        public DateTime DateAdmitted { get; set; }
    }

    public class PatientDrug
    {
        public string Patient { get; set; }
        public string Drug { get; set; }
    }


    internal class Program
    {
        private static void Main(string[] args)
        {
            DataTable patientDrugDataTable = GetPatientDrugTable();
            DataTable patientDataTable = GetPatientTable();

            string patientDrugJson = GetJsonFromDataTable<PatientDrug>(patientDrugDataTable);
            Console.WriteLine("Json for PatientDrug:n{0}",patientDrugJson);

            string patientJson = GetJsonFromDataTable<Patient>(patientDataTable);
            Console.WriteLine("nJson for Patient:n{0}", patientJson);

            Console.WriteLine("nnPress a key to Exit...");
            Console.ReadKey();
        }

        private static DataTable GetPatientDrugTable()
        {
        //
        // Here we create a DataTable with four columns.
        //
        DataTable table = new DataTable();
        table.Columns.Add("Dosage", typeof(int));
        table.Columns.Add("Drug", typeof(string));
        table.Columns.Add("Patient", typeof(string));
        table.Columns.Add("Date", typeof(DateTime));

        //
        // Here we add five DataRows.
        //
        table.Rows.Add(25, "Indocin", "David", DateTime.Now);
        table.Rows.Add(50, "Enebrel", "Sam", DateTime.Now);
        table.Rows.Add(10, "Hydralazine", "Christoff", DateTime.Now);
        table.Rows.Add(21, "Combivent", "Janet", DateTime.Now);
        table.Rows.Add(100, "Dilantin", "Melanie", DateTime.Now);
        return table;
        }

        private static DataTable GetPatientTable()
        {
            //
            // Here we create a DataTable with four columns.
            //
            DataTable table = new DataTable();
            table.Columns.Add("NumberOfIllnesses", typeof(int));
            table.Columns.Add("PatientID", typeof(string));
            table.Columns.Add("FullName", typeof(string));
            table.Columns.Add("DateAdmitted", typeof(DateTime));
            table.Columns.Add("StreetAddress1", typeof(string));
            table.Columns.Add("City", typeof(string));
            table.Columns.Add("State", typeof(string));
            //
            // Here we add five DataRows.
            //
            table.Rows.Add(2, "PAT-00001", "David", DateTime.Now, "1 Mill Ln", "Schenectady", "NY");
            table.Rows.Add(1, "PAT-00002", "Sam", DateTime.Now, "1915 Boylston Steet", "Boston", "MA");
            table.Rows.Add(3, "PAT-00003", "Christoff", DateTime.Now, "15 Polk Steet", "San Francisco", "CA");
            table.Rows.Add(4, "PAT-00004", "Janet", DateTime.Now, "10 Waverly St", "Los Angeles", "CA");
            table.Rows.Add(5, "PAT-00005", "Melanie", DateTime.Now, "50 Kapaa St", "Kailua", "HI");
            return table;
        }

        /// <summary>
        /// Returns Json representation of Generic class with only matching properties from the DataTable (passed as parameter)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static string GetJsonFromDataTable<T>(DataTable dt) where T : new()
        {
            string json = GetJson(dt);
            return JsonConvert.SerializeObject(JsonConvert.DeserializeObject<List<T>>(json));
        }

        /// <summary>
        /// Returns a JSON string for entire DataTable (passed as parameter)
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static string GetJson(DataTable dt)
        {
            System.Web.Script.Serialization.JavaScriptSerializer serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
            List<Dictionary<string, object>> rows = (from DataRow dr in dt.Rows select dt.Columns.Cast<DataColumn>().ToDictionary(col => col.ColumnName.Trim(), col => dr[col])).ToList();
            return serializer.Serialize(rows);
        }
    }
}
 

Объяснение кода:

Обратите внимание, что у меня есть 2 класса, Patient и PatientDrug . Я написал вспомогательные методы для возврата таблиц данных для обоих классов, которые имеют дополнительные столбцы. Затем следующие 2 строки получают JSON для представления класса для Patient и PatientDrug соответственно, игнорируя дополнительные столбцы данных в DataTable, которые не соответствуют именам.

 string patientDrugJson = GetJsonFromDataTable<PatientDrug>(patientDrugDataTable);
string patientJson = GetJsonFromDataTable<Patient>(patientDataTable);
 

Вывод в консольных окнах (строки json)

введите описание изображения здесь

Комментарии:

1. Большое спасибо за этот рабочий пример. Мне нужно будет изучить код, прежде чем я смогу официально принять ответ — вы используете некоторые новые для меня навыки C # 🙂