জেনেরিক তালিকাটি রূপান্তর / ডেটা টেবেলে গণনাযোগ্য?


261

আমার কাছে কয়েকটি পদ্ধতি রয়েছে যা বিভিন্ন জেনেরিক তালিকাকে দেয়।

কোন শ্রেণীর স্থিতিশীল পদ্ধতিতে বা কোনও তালিকাকে ডেটেবলে রূপান্তর করতে কোন কিছুই নেই? আমি কেবল কল্পনা করতে পারি তা হ'ল এটি করতে রিফ্লেকশনটি ব্যবহার করুন।

যদি আমার কাছে এটি থাকে:

List<Whatever> whatever = new List<Whatever>();

(এই পরবর্তী কোডটি অবশ্যই কাজ করে না, তবে আমি এর সম্ভাবনাটি দেখতে চাই:

DataTable dt = (DataTable) whatever;

2
অবশ্যই, একটি ভাল প্রশ্ন হবে "কেন?" - যখন তালিকাটি <T> অনেক ক্ষেত্রে ডেটাটেবলের থেকে ভাল সরঞ্জাম ;- প্রতিটি তাদের নিজস্ব বলে মনে হয় ...
মার্ক গ্র্যাভেল

1
আমি মনে করি এটি একটি এই প্রশ্নের সদৃশ হতে পারে: stackoverflow.com/questions/523153/… এর কাছাকাছি একটি অভিন্ন উত্তরও রয়েছে। :-)
মেজয়েড

2
@ মার্কগ্রাভেল: আমার "কেন?" তালিকাটি <T> ম্যানিপুলেশন (কলাম এবং সারিগুলি অনুসরণ করে)। আমি একটি তালিকা <টি> থেকে একটি মূল তৈরি করার চেষ্টা করছি এবং প্রতিচ্ছবিটির মাধ্যমে বৈশিষ্ট্যগুলি অ্যাক্সেস করা এটি একটি ব্যথা। আমি এটা ভুল করছি?
এডুয়ার্ডো মোল্টেনি

1
@ এডুয়ার্ডো সেখানে প্রতিবিম্বের ব্যথা অপসারণের জন্য অনেকগুলি সরঞ্জাম রয়েছে - ফাস্টমেবার মনে পড়ছে। এটা তোলে পারে হতে একটি DataTable নির্দিষ্ট পরিস্থিতিতে দরকারী - এটা সব প্রসঙ্গ উপর নির্ভর করে। বিকল্পগুলির বিকল্পগুলি এবং তাদের পরিস্থিতি বিবেচনা করার জন্য সময় না নিয়েই সবচেয়ে বড় সমস্যা হ'ল লোকেরা সমস্ত ডেটা স্টোরেজের জন্য ডেটা টেবিল ব্যবহার করে কারণ এটি বিদ্যমান
মার্ক Gravell

@ এডুয়ার্ডো মল্টেনি আপনি যদি আগ্রহী হন তবে আমি এর সরাসরি সমর্থন পেতে ফাস্টমেমারকে আপডেট করেছি - আপডেট উত্তরটি দেখুন
মার্ক গ্র্যাভেল

উত্তর:


325

এখানে নিউগেট থেকে ফাস্টমেম্বার ব্যবহার করে একটি দুর্দান্ত 2013 আপডেট রয়েছে :

IEnumerable<SomeType> data = ...
DataTable table = new DataTable();
using(var reader = ObjectReader.Create(data)) {
    table.Load(reader);
}

এটি সর্বোচ্চ পারফরম্যান্সের জন্য ফাস্টমেম্বারের মেটা-প্রোগ্রামিং এপিআই ব্যবহার করে। আপনি যদি এটি নির্দিষ্ট সদস্যদের মধ্যে সীমাবদ্ধ রাখতে চান (বা আদেশটি প্রয়োগ করুন), তবে আপনি এটিও করতে পারেন:

IEnumerable<SomeType> data = ...
DataTable table = new DataTable();
using(var reader = ObjectReader.Create(data, "Id", "Name", "Description")) {
    table.Load(reader);
}

সম্পাদকের ডিস / দাবিদার: ফাস্টমেমার একটি মার্ক গ্র্যাভেল প্রকল্প। এর সোনার এবং পূর্ণ-উড়ে!


হ্যাঁ, এটি এর ঠিক বিপরীত এই এক; প্রতিফলন যথেষ্ট হবে - বা আপনার যদি দ্রুত প্রয়োজন হয়, HyperDescriptor2.0 বা সম্ভবত Expression3.5 এ। আসলে, HyperDescriptorপর্যাপ্ত চেয়ে বেশি হওয়া উচিত।

উদাহরণ স্বরূপ:

// remove "this" if not on C# 3.0 / .NET 3.5
public static DataTable ToDataTable<T>(this IList<T> data)
{
    PropertyDescriptorCollection props =
        TypeDescriptor.GetProperties(typeof(T));
    DataTable table = new DataTable();
    for(int i = 0 ; i < props.Count ; i++)
    {
        PropertyDescriptor prop = props[i];
        table.Columns.Add(prop.Name, prop.PropertyType);
    }
    object[] values = new object[props.Count];
    foreach (T item in data)
    {
        for (int i = 0; i < values.Length; i++)
        {
            values[i] = props[i].GetValue(item);
        }
        table.Rows.Add(values);
    }
    return table;        
}

এখন এক লাইনের সাহায্যে আপনি প্রতিবিম্বের তুলনায় এটিকে বহুগুণ দ্রুত করতে পারবেন ( HyperDescriptorবস্তুর ধরণের জন্য সক্ষম করে T)।


পুনরায় পারফরম্যান্স ক্যোয়ারী সম্পাদনা করুন; ফলাফল সহ একটি পরীক্ষার ছদ্মবেশ এখানে:

Vanilla 27179
Hyper   6997

আমার সন্দেহ হয় যে বাধাটি সদস্যের অ্যাক্সেস থেকে DataTableপারফরম্যান্সে চলে এসেছে ... আমি সন্দেহ করি যে আপনি এতে আরও উন্নতি করবেন ...

কোড:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
public class MyData
{
    public int A { get; set; }
    public string B { get; set; }
    public DateTime C { get; set; }
    public decimal D { get; set; }
    public string E { get; set; }
    public int F { get; set; }
}

static class Program
{
    static void RunTest(List<MyData> data, string caption)
    {
        GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
        GC.WaitForPendingFinalizers();
        GC.WaitForFullGCComplete();
        Stopwatch watch = Stopwatch.StartNew();
        for (int i = 0; i < 500; i++)
        {
            data.ToDataTable();
        }
        watch.Stop();
        Console.WriteLine(caption + "\t" + watch.ElapsedMilliseconds);
    }
    static void Main()
    {
        List<MyData> foos = new List<MyData>();
        for (int i = 0 ; i < 5000 ; i++ ){
            foos.Add(new MyData
            { // just gibberish...
                A = i,
                B = i.ToString(),
                C = DateTime.Now.AddSeconds(i),
                D = i,
                E = "hello",
                F = i * 2
            });
        }
        RunTest(foos, "Vanilla");
        Hyper.ComponentModel.HyperTypeDescriptionProvider.Add(
            typeof(MyData));
        RunTest(foos, "Hyper");
        Console.ReadLine(); // return to exit        
    }
}

4
ভাল "যেমনটি", এটি প্রতিবিম্বের মতো দ্রুত হবে। আপনি যদি হাইপারডেস্কিটার সক্ষম করেন, এটি প্রতিবিম্বের হাত নীচে ছুঁড়ে ফেলবে ... আমি একটি দ্রুত পরীক্ষা চালাব ... (2 মিনিট)
মার্ক গ্র্যাভেল

এক্সপ্রেশনটি 3.5 এর জন্য উল্লেখ করা হয়েছিল। যদি এটি কীভাবে কোডটি প্রভাবিত করে তবে কী কোনও নমুনা রয়েছে?
মাইকমিট

3
@ মার্কগ্রাভেল হ্যাঁ আমি এক্সপ্রেশন সমাধানে খুব আগ্রহী হব। দ্রুত কিছু শেখার প্রভাবের জন্য। আপনাকে ধন্যবাদ মার্ক!
এলিজাবেথ

11
@ এললেসিডিল আমি এ জাতীয় বিষয়গুলি স্পষ্টভাবে প্রকাশ করার জন্য মনে রাখার জন্য প্রচেষ্টার চেষ্টা করি, তবে যেহেতু আমি কোনও কিছু বিক্রি করছি না (বরং বহু ঘন্টার কাজটি নিখরচায় করে দিচ্ছি ) আমি স্বীকার করি যে আমি এখানে প্রচুর পরিমাণে অপরাধবোধ অনুভব করি না ...
মার্ক গ্রাভেল

2
আপনার পদ্ধতি টুডাটাবেল অযোগ্য ক্ষেত্রগুলিকে সমর্থন করে না: অতিরিক্ত তথ্য: ডেটাসেট সিস্টেমকে সমর্থন করে না ul নন <>।
ডেইনিয়াস ক্রেইভিস

235

নালামযোগ্য প্রকারগুলি এবং নাল মানগুলি হ্যান্ডেল করার জন্য আমাকে মার্ক গ্রাভেলের নমুনা কোডটি পরিবর্তন করতে হয়েছিল। আমি নীচে একটি কাজের সংস্করণ অন্তর্ভুক্ত করেছি। ধন্যবাদ মার্ক।

public static DataTable ToDataTable<T>(this IList<T> data)
{
    PropertyDescriptorCollection properties = 
        TypeDescriptor.GetProperties(typeof(T));
    DataTable table = new DataTable();
    foreach (PropertyDescriptor prop in properties)
        table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
    foreach (T item in data)
    {
        DataRow row = table.NewRow();
        foreach (PropertyDescriptor prop in properties)
             row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
        table.Rows.Add(row);
    }
    return table;
}

এটি একটি দুর্দান্ত উত্তর। আমি এই উদাহরণটি এমন একটি দলকে তালিকার দ্বারা পরিচালনা করতে প্রসারিত দেখতে দেখতে চাই যাতে কোনও আইটেমের সম্পত্তি থাকবে এবং উপরে একইভাবে কলাম তৈরি করা উচিত।
অজানা কোডার

2
@ জিম বিম অর্জনের জন্য, গ্রুপবিয়ের রিটার্নটি স্বীকার করার জন্য পদ্ধতিতে স্বাক্ষরটি পরিবর্তন করুন: public static DataTable ToDataTable<TKey, T>(this IEnumerable<IGrouping<TKey, T>> data) তারপরে, ফরচ লুপের আগে একটি অতিরিক্ত কলাম table.Columns.Add("Key", Nullable.GetUnderlyingType(typeof(TKey)) ?? typeof(TKey)); যুক্ত করুন : এবং তারপরে আপনি দলগুলি পুনরাবৃত্তি করবেন এমন ডেটা লুপের চারপাশে একটি লুপ যুক্ত করুন: ফোরচ (আইগ্রুপিং <টি কে, টি> উপায়ে গোষ্ঠী) ach পূর্বাভাস (গ্রুপে টি আইটেম te আইটেম) details সম্পূর্ণ বিবরণের জন্য এই জিআইএসটি দেখুন: gist.github.com/rickdailey/8679306
রিক ডেইলি

আরে, অভ্যন্তরীণ বস্তুগুলির সাথে কোনও জিনিস পরিচালনা করার উপায় আছে? আমি কেবল চাই
পিতামাত্ত

@ ওহ, আমি নিশ্চিত যে সেখানে আছে। তবে আমি যা করছি তার সাথে আমার সেই কার্যকারিতাটির সত্যই প্রয়োজন ছিল না এবং তাই অন্য কারও জন্য এটি বাড়িয়ে দেওয়া হয়েছিল। :)
মেরি হামলিন

1
এটি একটি পুরানো পোস্ট তাই এই মন্তব্যটি কতটা কার্যকর তা নিশ্চিত নন তবে এই ToDataTableপদ্ধতিতে একটি ছদ্মবেশী বাগ রয়েছে । যদি Tপ্রয়োগ typeof(T)করে ইন্টারফেসটি বস্তুর প্রকৃত শ্রেণির চেয়ে ইন্টারফেসের ধরণটি ফিরিয়ে দিতে পারে, ফলস্বরূপ একটি খালি থাকে DataTable। এটির পরিবর্তে এটি data.First().GetType()ঠিক করা উচিত।
লুকাস

14

মার্ক টেস্টের মতো মান ধরণের সাথে এটির কাজ করতে উত্তরের একটি ছোট্ট পরিবর্তন List<string>:

public static DataTable ListToDataTable<T>(IList<T> data)
{
    DataTable table = new DataTable();

    //special handling for value types and string
    if (typeof(T).IsValueType || typeof(T).Equals(typeof(string)))
    {

        DataColumn dc = new DataColumn("Value");
        table.Columns.Add(dc);
        foreach (T item in data)
        {
            DataRow dr = table.NewRow();
            dr[0] = item;
            table.Rows.Add(dr);
        }
    }
    else
    {
        PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
        foreach (PropertyDescriptor prop in properties)
        {
            table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
        }
        foreach (T item in data)
        {
            DataRow row = table.NewRow();
            foreach (PropertyDescriptor prop in properties)
            {
                try
                {
                    row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
                }
                catch (Exception ex)
                {
                    row[prop.Name] = DBNull.Value;
                }
            }
            table.Rows.Add(row);
        }
    }
    return table;
}

তালিকা <int> এর জন্য এটি কীভাবে তৈরি করবেন?
মুফ্লিক্স

1
উপরের পদ্ধতিটি int (এবং অন্যান্য মান ধরণের) জন্যও কাজ করবে ... int একটি মান ধরণের। দেখুন: এমএসডিএন.মাইক্রোসফটকম /en-us/library/s1ax56ch.aspx
অনুর ওমর

আমি এটি পছন্দ করি কারণ এটি কোনও এক্সটেনশন পদ্ধতি ব্যবহারের উপর নির্ভর করে না। পুরানো কোডবেসের জন্য ভাল কাজ করে যাতে এক্সটেনশন পদ্ধতিতে অ্যাক্সেস নাও থাকতে পারে।
ওয়েবওয়ার্ম

13

এটি সমাধানগুলির একটি সহজ মিশ্রণ। এটি নলযোগ্য প্রকারের সাথে কাজ করে।

public static DataTable ToDataTable<T>(this IList<T> list)
{
  PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(T));
  DataTable table = new DataTable();
  for (int i = 0; i < props.Count; i++)
  {
    PropertyDescriptor prop = props[i];
    table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
  }
  object[] values = new object[props.Count];
  foreach (T item in list)
  {
    for (int i = 0; i < values.Length; i++)
      values[i] = props[i].GetValue(item) ?? DBNull.Value;
    table.Rows.Add(values);
  }
  return table;
}

এই সমাধানটি ত্রুটিযুক্ত প্রবণ কারণ এটি টি শ্রেণিতে সম্পত্তি ঘোষণার আদেশের উপর নির্ভর করে।
ওয়াহিদ গাদিরি

10

এমএসডিএন-এ এই লিঙ্কটি দেখার জন্য মূল্যবান: কীভাবে: কপিরাইটডেটা টেবিলটি কার্যকর করুন <T> যেখানে জেনেরিক টাইপ টি কোনও ডাটাআর নয়

এটি একটি এক্সটেনশন পদ্ধতি যুক্ত করে যা আপনাকে এটি করতে দেয়:

// Create a sequence. 
Item[] items = new Item[] 
{ new Book{Id = 1, Price = 13.50, Genre = "Comedy", Author = "Gustavo Achong"}, 
  new Book{Id = 2, Price = 8.50, Genre = "Drama", Author = "Jessie Zeng"},
  new Movie{Id = 1, Price = 22.99, Genre = "Comedy", Director = "Marissa Barnes"},
  new Movie{Id = 1, Price = 13.40, Genre = "Action", Director = "Emmanuel Fernandez"}};

// Query for items with price greater than 9.99.
var query = from i in items
             where i.Price > 9.99
             orderby i.Price
             select i;

// Load the query results into new DataTable.
DataTable table = query.CopyToDataTable();

@ পলউইলিয়ামস ধন্যবাদ, আমি এতক্ষণ কোনও সমস্যা ছাড়াই বছরের পর বছর ধরে এই কোডটি ব্যবহার করি। কিন্তু যেহেতু আমি থেকে উদাহরণস্বরূপ কোড কপি করা হয়নি মাইক্রোসফট এবং শুধুমাত্র ওয়েবসাইট অন্যান্য সমাধানের অন্তত উত্তর সর্বোত্তম কার্যাভ্যাস সঙ্গে আরো অনুবর্তী হয় লিঙ্ক stackoverflow.com/help/how-to-answer
ইয়ুর্গেন Steinblock

8

অন্য পদ্ধতির উপরোক্ত বিষয়গুলি:

  List<WhateEver> lst = getdata();
  string json = Newtonsoft.Json.JsonConvert.SerializeObject(lst);
  DataTable pDt = JsonConvert.DeserializeObject<DataTable>(json);

খুব ভাল ... তবে এটি 'System.OutOfMemoryException' টাইপের ব্যতিক্রম ছুঁড়ে দিয়েছে। আমি এটি 500,000 আইটেম সহ ব্যবহার করেছি ... তবে এর জন্য আপনাকে ধন্যবাদ।
st_stefanov

এটি নেট পর্যন্ত আমি সবচেয়ে পরিষ্কার সমাধান খুঁজে পেয়েছি। মহান কাজ!
সারা

7
public DataTable ConvertToDataTable<T>(IList<T> data)
{
    PropertyDescriptorCollection properties =
        TypeDescriptor.GetProperties(typeof(T));

    DataTable table = new DataTable();

    foreach (PropertyDescriptor prop in properties)
            table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);

    foreach (T item in data)
    {
        DataRow row = table.NewRow();
        foreach (PropertyDescriptor prop in properties)
        {
           row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
        }
        table.Rows.Add(row);
    }
    return table;
}

3
যদিও এই কোডটি প্রশ্নের উত্তর দিতে পারে, কেন এবং / অথবা এই কোডটির প্রশ্নের উত্তর কীভাবে তার দীর্ঘমেয়াদী মানকে উন্নত করে তা সম্পর্কিত অতিরিক্ত প্রসঙ্গ সরবরাহ করে।
কেয়েস

এই সমাধানটি ত্রুটিযুক্ত প্রবণ কারণ এটি টি শ্রেণিতে সম্পত্তি ঘোষণার আদেশের উপর নির্ভর করে।
ওয়াহিদ গাদিরি

6

মার্ক গ্র্যাভেলের উত্তর কিন্তু ভিবি.এনইটে

Public Shared Function ToDataTable(Of T)(data As IList(Of T)) As DataTable
    Dim props As PropertyDescriptorCollection = TypeDescriptor.GetProperties(GetType(T))
    Dim table As New DataTable()
    For i As Integer = 0 To props.Count - 1
            Dim prop As PropertyDescriptor = props(i)
            table.Columns.Add(prop.Name, prop.PropertyType)
    Next
    Dim values As Object() = New Object(props.Count - 1) {}
    For Each item As T In data
            For i As Integer = 0 To values.Length - 1
                    values(i) = props(i).GetValue(item)
            Next
            table.Rows.Add(values)
    Next
    Return table
End Function

6

এটা চেষ্টা কর

public static DataTable ListToDataTable<T>(IList<T> lst)
{

    currentDT = CreateTable<T>();

    Type entType = typeof(T);

    PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(entType);
    foreach (T item in lst)
    {
        DataRow row = currentDT.NewRow();
        foreach (PropertyDescriptor prop in properties)
        {

            if (prop.PropertyType == typeof(Nullable<decimal>) || prop.PropertyType == typeof(Nullable<int>) || prop.PropertyType == typeof(Nullable<Int64>))
            {
                if (prop.GetValue(item) == null)
                    row[prop.Name] = 0;
                else
                    row[prop.Name] = prop.GetValue(item);
            }
            else
                row[prop.Name] = prop.GetValue(item);                    

        }
        currentDT.Rows.Add(row);
    }

    return currentDT;
}

public static DataTable CreateTable<T>()
{
    Type entType = typeof(T);
    DataTable tbl = new DataTable(DTName);
    PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(entType);
    foreach (PropertyDescriptor prop in properties)
    {
        if (prop.PropertyType == typeof(Nullable<decimal>))
             tbl.Columns.Add(prop.Name, typeof(decimal));
        else if (prop.PropertyType == typeof(Nullable<int>))
            tbl.Columns.Add(prop.Name, typeof(int));
        else if (prop.PropertyType == typeof(Nullable<Int64>))
            tbl.Columns.Add(prop.Name, typeof(Int64));
        else
             tbl.Columns.Add(prop.Name, prop.PropertyType);
    }
    return tbl;
}

6
It's also possible through XmlSerialization.
The idea is - serialize to `XML` and then `readXml` method of `DataSet`.

I use this code (from an answer in SO, forgot where)

        public static string SerializeXml<T>(T value) where T : class
    {
        if (value == null)
        {
            return null;
        }

        XmlSerializer serializer = new XmlSerializer(typeof(T));

        XmlWriterSettings settings = new XmlWriterSettings();

        settings.Encoding = new UnicodeEncoding(false, false);
        settings.Indent = false;
        settings.OmitXmlDeclaration = false;
        // no BOM in a .NET string

        using (StringWriter textWriter = new StringWriter())
        {
            using (XmlWriter xmlWriter = XmlWriter.Create(textWriter, settings))
            {
               serializer.Serialize(xmlWriter, value);
            }
            return textWriter.ToString();
        }
    }

so then it's as simple as:

            string xmlString = Utility.SerializeXml(trans.InnerList);

        DataSet ds = new DataSet("New_DataSet");
        using (XmlReader reader = XmlReader.Create(new StringReader(xmlString)))
        { 
            ds.Locale = System.Threading.Thread.CurrentThread.CurrentCulture;
            ds.ReadXml(reader); 
        }

Not sure how it stands against all the other answers to this post, but it's also a possibility.

5

এই কাজটি সম্পাদন করার জন্য আমি নিজে একটি ছোট গ্রন্থাগার লিখেছি। এটি কেবলমাত্র প্রথমবারের জন্য কোনও ডেটাতেবলে কোনও বস্তুর প্রকারের অনুবাদ করার জন্য প্রতিবিম্ব ব্যবহার করে। এটি এমন একটি পদ্ধতি নির্গত করে যা কোনও কাজের ধরণের অনুবাদ করে সমস্ত কাজ করবে।

এটি দ্রুত জ্বলছে। আপনি এটি এখানে খুঁজে পেতে পারেন: গুগল কোডে মডেলশ্রেডার


2

আমাকে একটি বিকল্প সমাধানও নিয়ে আসতে হয়েছিল, কারণ এখানে তালিকাভুক্ত বিকল্পগুলির মধ্যে কোনওটিই আমার ক্ষেত্রে কাজ করে নি। আমি একটি আইনিউমারেবল ব্যবহার করছিলাম যা একটি আইনামিউরেবল ফিরিয়েছিল এবং বৈশিষ্ট্যগুলি গণনা করা যায়নি। এটি কৌশলটি করেছে:

// remove "this" if not on C# 3.0 / .NET 3.5
public static DataTable ConvertToDataTable<T>(this IEnumerable<T> data)
{
    List<IDataRecord> list = data.Cast<IDataRecord>().ToList();

    PropertyDescriptorCollection props = null;
    DataTable table = new DataTable();
    if (list != null && list.Count > 0)
    {
        props = TypeDescriptor.GetProperties(list[0]);
        for (int i = 0; i < props.Count; i++)
        {
            PropertyDescriptor prop = props[i];
            table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
        }
    }
    if (props != null)
    {
        object[] values = new object[props.Count];
        foreach (T item in data)
        {
            for (int i = 0; i < values.Length; i++)
            {
                values[i] = props[i].GetValue(item) ?? DBNull.Value;
            }
            table.Rows.Add(values);
        }
    }
    return table;
}

2
  using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using System.ComponentModel;

public partial class Default3 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        DataTable dt = new DataTable();
        dt = lstEmployee.ConvertToDataTable();
    }
    public static DataTable ConvertToDataTable<T>(IList<T> list) where T : class
    {
        try
        {
            DataTable table = CreateDataTable<T>();
            Type objType = typeof(T);
            PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(objType);
            foreach (T item in list)
            {
                DataRow row = table.NewRow();
                foreach (PropertyDescriptor property in properties)
                {
                    if (!CanUseType(property.PropertyType)) continue;
                    row[property.Name] = property.GetValue(item) ?? DBNull.Value;
                }

                table.Rows.Add(row);
            }
            return table;
        }
        catch (DataException ex)
        {
            return null;
        }
        catch (Exception ex)
        {
            return null;
        }

    }
    private static DataTable CreateDataTable<T>() where T : class
    {
        Type objType = typeof(T);
        DataTable table = new DataTable(objType.Name);
        PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(objType);
        foreach (PropertyDescriptor property in properties)
        {
            Type propertyType = property.PropertyType;
            if (!CanUseType(propertyType)) continue;

            //nullables must use underlying types
            if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
                propertyType = Nullable.GetUnderlyingType(propertyType);
            //enums also need special treatment
            if (propertyType.IsEnum)
                propertyType = Enum.GetUnderlyingType(propertyType);
            table.Columns.Add(property.Name, propertyType);
        }
        return table;
    }


    private static bool CanUseType(Type propertyType)
    {
        //only strings and value types
        if (propertyType.IsArray) return false;
        if (!propertyType.IsValueType && propertyType != typeof(string)) return false;
        return true;
    }
}

2

আমি বুঝতে পারি যে এটি কিছু সময়ের জন্য বন্ধ হয়ে গেছে; তবে, আমি এই নির্দিষ্ট সমস্যার সমাধান পেয়েছি তবে সামান্য বাঁক দরকার: কলাম এবং ডেটা টেবিলের পূর্বনির্ধারিত / ইতিমধ্যে ইনস্ট্যান্ট করা দরকার। তারপরে আমার কেবল ডাটা টেবিলের মধ্যে প্রকারগুলি সন্নিবেশ করা প্রয়োজন।

আমি এখানে যা করেছি তার উদাহরণ এখানে:

public static class Test
{
    public static void Main()
    {
        var dataTable = new System.Data.DataTable(Guid.NewGuid().ToString());

        var columnCode = new DataColumn("Code");
        var columnLength = new DataColumn("Length");
        var columnProduct = new DataColumn("Product");

        dataTable.Columns.AddRange(new DataColumn[]
            {
                columnCode,
                columnLength,
                columnProduct
            });

        var item = new List<SomeClass>();

        item.Select(data => new
        {
            data.Id,
            data.Name,
            data.SomeValue
        }).AddToDataTable(dataTable);
    }
}

static class Extensions
{
    public static void AddToDataTable<T>(this IEnumerable<T> enumerable, System.Data.DataTable table)
    {
        if (enumerable.FirstOrDefault() == null)
        {
            table.Rows.Add(new[] {string.Empty});
            return;
        }

        var properties = enumerable.FirstOrDefault().GetType().GetProperties();

        foreach (var item in enumerable)
        {
            var row = table.NewRow();
            foreach (var property in properties)
            {
                row[property.Name] = item.GetType().InvokeMember(property.Name, BindingFlags.GetProperty, null, item, null);
            }
            table.Rows.Add(row);
        }
    }
}

আপনি উদাহরণ দিয়ে আমাকে দেখাতে পারেন? আমি কীভাবে অ্যাডডোডেটাবল () পদ্ধতির জন্য এক্সটেনশন পদ্ধতিটি ব্যবহার করি
অভিষেক বি

এই কোডটির ইতিমধ্যে এটিতে একটি উদাহরণ রয়েছে - প্রধান () পদ্ধতিটি একবার দেখুন। কোডের শেষ বিটটিতে এক্সটেনশনটি ব্যবহার করা হচ্ছে।
ব্রেন্টন

: আরো পড়ার জন্য, দয়া করে এক্সটেনশন পদ্ধতিগুলির দুটিই MSDN থেকে এই নিবন্ধটি তাকান msdn.microsoft.com/en-us/library/bb383977.aspx
brenton

2

আপনি .NET কোর ব্যবহার করছেন তবে একটি 2019 উত্তর - নিউগ টোডাটাবেবল লাইব্রেরি ব্যবহার করুন । সুবিধাদি:

দাবি পরিত্যাগী অস্বীকার - আমি ToDataTable এর লেখক

পারফরম্যান্স - আমি কয়েকটি বেঞ্চমার্ক জুড়েছি। নেট পরীক্ষা এবং সেগুলি টোডেটা টেবিলের রেপোতে অন্তর্ভুক্ত করেছি । । ফলাফলগুলি নিম্নরূপ ছিল:

একটি 100,000 সারি ডেটাবেবল তৈরি করা :

                           MacOS         Windows
Reflection                 818.5 ms      818.3 ms
FastMember from           1105.5 ms      976.4 ms
 Mark's answer
Improved FastMember        524.6 ms      456.4 ms
ToDataTable                449.0 ms      376.5 ms

মার্কের উত্তরে প্রস্তাবিত ফাস্টমেম্বার পদ্ধতিটি মেরির উত্তরের চেয়ে খারাপ সম্পাদন করেছিল বলে মনে হয়েছিল যার প্রতিফলন ব্যবহৃত হয়েছিল, তবে আমি ফাস্টমেম্বার ব্যবহার করে অন্য পদ্ধতিটি রোল করেছি TypeAccessorএবং এটি আরও ভাল অভিনয় করেছে। তবুও টোডাটাবেল প্যাকেজটি প্রচুর ছাড়িয়ে গেছে।


1

আপনি যদি ভিবি.এনইটি ব্যবহার করেন তবে এই শ্রেণিটি কাজটি করে।

Imports System.Reflection
''' <summary>
''' Convert any List(Of T) to a DataTable with correct column types and converts Nullable Type values to DBNull
''' </summary>

Public Class ConvertListToDataset

    Public Function ListToDataset(Of T)(ByVal list As IList(Of T)) As DataTable

        Dim dt As New DataTable()
        '/* Create the DataTable columns */
        For Each pi As PropertyInfo In GetType(T).GetProperties()
            If pi.PropertyType.IsValueType Then
                Debug.Print(pi.Name)
            End If
            If IsNothing(Nullable.GetUnderlyingType(pi.PropertyType)) Then
                dt.Columns.Add(pi.Name, pi.PropertyType)
            Else
                dt.Columns.Add(pi.Name, Nullable.GetUnderlyingType(pi.PropertyType))
            End If
        Next

        '/* Populate the DataTable with the values in the Items in List */
        For Each item As T In list
            Dim dr As DataRow = dt.NewRow()
            For Each pi As PropertyInfo In GetType(T).GetProperties()
                dr(pi.Name) = IIf(IsNothing(pi.GetValue(item)), DBNull.Value, pi.GetValue(item))
            Next
            dt.Rows.Add(dr)
        Next
        Return dt

    End Function

End Class

1

আপনার ক্লাসে যদি আপনার বৈশিষ্ট্য থাকে তবে কোডের এই লাইনটি ঠিক আছে !!

PropertyDescriptorCollection props =
            TypeDescriptor.GetProperties(typeof(T));

তবে আপনার যদি সর্বসাধারণের ক্ষেত্র থাকে তবে এটি ব্যবহার করুন:

public static DataTable ToDataTable<T>(  IList<T> data)
        {
        FieldInfo[] myFieldInfo;
        Type myType = typeof(T);
        // Get the type and fields of FieldInfoClass.
        myFieldInfo = myType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance
            | BindingFlags.Public);

        DataTable dt = new DataTable();
        for (int i = 0; i < myFieldInfo.Length; i++)
            {
            FieldInfo property = myFieldInfo[i];
            dt.Columns.Add(property.Name, property.FieldType);
            }
        object[] values = new object[myFieldInfo.Length];
        foreach (T item in data)
            {
            for (int i = 0; i < values.Length; i++)
                {
                values[i] = myFieldInfo[i].GetValue(item);
                }
            dt.Rows.Add(values);
            }
        return dt;
        }

মূল উত্তরটি উপরের থেকে, আমি কেবল বৈশিষ্ট্যের পরিবর্তে ক্ষেত্রগুলি ব্যবহার করতে সম্পাদনা করেছি

এবং এটি ব্যবহার করতে

 DataTable dt = new DataTable();
            dt = ToDataTable(myBriefs);
            gridData.DataSource = dt;
            gridData.DataBind();

1

জেনেরিক তালিকাটিকে ডেটা টেবিলে রূপান্তর করতে, আপনি ডেটা টেবেল জেনারেটরটি ব্যবহার করতে পারেন

এই লাইব্রেরিটি আপনাকে মাল্টি-ফিচারের মতো আপনার তালিকাটিকে একটি ডাটা টেবিলে রূপান্তর করতে দেয়

  • ডেটা টেবিল শিরোনাম অনুবাদ করুন
  • দেখানোর জন্য কিছু কলাম নির্দিষ্ট করুন

1
  private DataTable CreateDataTable(IList<T> item)
        {
            Type type = typeof(T);
            var properties = type.GetProperties();

            DataTable dataTable = new DataTable();
            foreach (PropertyInfo info in properties)
            {
                dataTable.Columns.Add(new DataColumn(info.Name, Nullable.GetUnderlyingType(info.PropertyType) ?? info.PropertyType));
            }

            foreach (T entity in item)
            {
                object[] values = new object[properties.Length];
                for (int i = 0; i < properties.Length; i++)
                {
                    values[i] = properties[i].GetValue(entity);
                }

                dataTable.Rows.Add(values);
            }
            return dataTable;
        }

1

জেনেরিক তালিকাটি ডেটা টেবেলে রূপান্তর করতে

নিউটনসফট.জসন ব্যবহার করে;

public DataTable GenericToDataTable(IList<T> list)
{
    var json = JsonConvert.SerializeObject(list);
    DataTable dt = (DataTable)JsonConvert.DeserializeObject(json, (typeof(DataTable)));
    return dt;
}

0

তালিকাটি ডেটাটেবলে রূপান্তর করার জন্য এটি সাধারণ কনসোল অ্যাপ্লিকেশন।

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.ComponentModel;

namespace ConvertListToDataTable
{
    public static class Program
    {
        public static void Main(string[] args)
        {
            List<MyObject> list = new List<MyObject>();
            for (int i = 0; i < 5; i++)
            {
                list.Add(new MyObject { Sno = i, Name = i.ToString() + "-KarthiK", Dat = DateTime.Now.AddSeconds(i) });
            }

            DataTable dt = ConvertListToDataTable(list);
            foreach (DataRow row in dt.Rows)
            {
                Console.WriteLine();
                for (int x = 0; x < dt.Columns.Count; x++)
                {
                    Console.Write(row[x].ToString() + " ");
                }
            }
            Console.ReadLine();
        }

        public class MyObject
        {
            public int Sno { get; set; }
            public string Name { get; set; }
            public DateTime Dat { get; set; }
        }

        public static DataTable ConvertListToDataTable<T>(this List<T> iList)
        {
            DataTable dataTable = new DataTable();
            PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(T));
            for (int i = 0; i < props.Count; i++)
            {
                PropertyDescriptor propertyDescriptor = props[i];
                Type type = propertyDescriptor.PropertyType;

                if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
                    type = Nullable.GetUnderlyingType(type);

                dataTable.Columns.Add(propertyDescriptor.Name, type);
            }
            object[] values = new object[props.Count];
            foreach (T iListItem in iList)
            {
                for (int i = 0; i < values.Length; i++)
                {
                    values[i] = props[i].GetValue(iListItem);
                }
                dataTable.Rows.Add(values);
            }
            return dataTable;
        }
    }
}

0

Se probó el método para que acepte campos con নাল।

// remove "this" if not on C# 3.0 / .NET 3.5
    public static DataTable ToDataTable<T>(IList<T> data)
    {
        PropertyDescriptorCollection props =
            TypeDescriptor.GetProperties(typeof(T));
        DataTable table = new DataTable();
        Type Propiedad = null;
        for (int i = 0; i < props.Count; i++)
        {
            PropertyDescriptor prop = props[i];
            Propiedad = prop.PropertyType;
            if (Propiedad.IsGenericType && Propiedad.GetGenericTypeDefinition() == typeof(Nullable<>)) 
            {
                Propiedad = Nullable.GetUnderlyingType(Propiedad);
            }
            table.Columns.Add(prop.Name, Propiedad);
        }
        object[] values = new object[props.Count];
        foreach (T item in data)
        {
            for (int i = 0; i < values.Length; i++)
            {
                values[i] = props[i].GetValue(item);
            }
            table.Rows.Add(values);
        }
        return table;
    }

2
স্ট্যাক ওভারফ্লোতে আপনাকে স্বাগতম । এটি একটি ইংরেজীভাষী ওয়েবসাইট, সুতরাং আপনার উত্তরগুলি পাশাপাশি ইংরেজিতে লিখুন।
পরী

0
 Dim counties As New List(Of County)
 Dim dtCounties As DataTable
 dtCounties = _combinedRefRepository.Get_Counties()
 If dtCounties.Rows.Count <> 0 Then
    For Each row As DataRow In dtCounties.Rows
      Dim county As New County
      county.CountyId = row.Item(0).ToString()
      county.CountyName = row.Item(1).ToString().ToUpper()
      counties.Add(county)
    Next
    dtCounties.Dispose()
 End If

0

আমি মনে করি এটি আরও সুবিধাজনক এবং ব্যবহার করা সহজ।

   List<Whatever> _lobj= new List<Whatever>(); 
    var json = JsonConvert.SerializeObject(_lobj);
                DataTable dt = (DataTable)JsonConvert.DeserializeObject(json, (typeof(DataTable)));

0

তালিকা / তথ্য = নতুন তালিকা (); var ডেটাডিটি = নিউটোনসফট.জসন.জসন কনভার্ট.ডিজারিয়ালাইজ অবজেক্ট (নিউটোনসফট.জসন.জসনকনভার্ট.সরিয়ালাইজ অবজেক্ট (ডেটা));



0

আপনি যদি প্রতিবিম্বটি ব্যবহার করতে চান এবং কলামগুলি অর্ডার সেট করতে / কেবল কয়েকটি কলাম অন্তর্ভুক্ত করতে / কিছু কলাম বাদ দিতে চেষ্টা করুন:

        private static DataTable ConvertToDataTable<T>(IList<T> data, string[] fieldsToInclude = null,
string[] fieldsToExclude = null)
    {
        PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
        DataTable table = new DataTable();
        foreach (PropertyDescriptor prop in properties)
        {
            if ((fieldsToInclude != null && !fieldsToInclude.Contains(prop.Name)) ||
                (fieldsToExclude != null && fieldsToExclude.Contains(prop.Name)))
                continue;
            table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
        }

        foreach (T item in data)
        {
            var atLeastOnePropertyExists = false;
            DataRow row = table.NewRow();
            foreach (PropertyDescriptor prop in properties)
            {

                if ((fieldsToInclude != null && !fieldsToInclude.Contains(prop.Name)) ||
(fieldsToExclude != null && fieldsToExclude.Contains(prop.Name)))
                    continue;

                row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
                atLeastOnePropertyExists = true;
            }

            if(atLeastOnePropertyExists) table.Rows.Add(row);
        }


        if (fieldsToInclude != null)
            SetColumnsOrder(table, fieldsToInclude);

        return table;

    }

    private static void SetColumnsOrder(DataTable table, params String[] columnNames)
    {
        int columnIndex = 0;
        foreach (var columnName in columnNames)
        {
            table.Columns[columnName].SetOrdinal(columnIndex);
            columnIndex++;
        }
    }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.