web-dev-qa-db-fra.com

Comment convertir DataTable en objet de classe

J'ai déjà développé une application qui renvoie DataTable partout.

Maintenant, mon client veut convertir (utiliser une partie de la pile de services), je dois donc renvoyer des objets DTO dans mon application.

Je ne veux pas changer mes procédures stockées existantes ou même ne pas vouloir utiliser LINQ autant que possible (je ne suis pas trop au courant avec LINQ).

Pour les petites fonctionnalités, je ne peux utiliser aucun problème avec Linq.

Ma question est la suivante: comment puis-je changer ma DataTable en objets de cette classe?

L'exemple de code est ci-dessous

string s = DateTime.Now.ToString();
DataTable dt = new DataTable();

dt.Columns.Add("id");
dt.Columns.Add("name");

for (int i = 0; i < 5000000; i++)
{
    DataRow dr = dt.NewRow();
    dr["id"] = i.ToString();
    dr["name"] = "name" + i.ToString();
    dt.Rows.Add(dr);

    dt.AcceptChanges();
}

List<Class1> clslist = new List<Class1>();

for (int i = 0; i < dt.Rows.Count; i++)
{
    Class1 cls = new Class1();
    cls.id = dt.Rows[i]["id"].ToString();
    cls.name = dt.Rows[i]["name"].ToString();
    clslist.Add(cls);
}

Response.Write(s);
Response.Write("<br>");
Response.Write(DateTime.Now.ToString());

Je sais, ce qui précède prend beaucoup de temps et j'essaie donc de trouver une solution alternative.

Existe-t-il un moyen alternatif (j'imagine, LINQ to DataTable) de convertir directement les lignes de tables en List<Class1>?

Je peux donc retourner des objets dans ma pile de services et continuer.

25
amit patel

Initialiser DataTable:

DataTable dt = new DataTable(); 
dt.Columns.Add("id", typeof(String)); 
dt.Columns.Add("name", typeof(String)); 
for (int i = 0; i < 5; i++)
{
    string index = i.ToString();
    dt.Rows.Add(new object[] { index, "name" + index });
}

Requête elle-même:

IList<Class1> items = dt.AsEnumerable().Select(row => 
    new Class1
        {
            id = row.Field<string>("id"),
            name = row.Field<string>("name")
        }).ToList();
62
sll

Amit, j'ai utilisé un moyen pour y parvenir avec moins de codage et de manière plus efficace.

mais il utilise Linq.

Je l'ai posté ici parce que peut-être la réponse aide-t-elle les autres.

Le code DAL ci-dessous convertit un objet datatable en une liste de YourViewModel facile à comprendre.

public static class DAL
{
        public static string connectionString = ConfigurationManager.ConnectionStrings["YourWebConfigConnection"].ConnectionString;

        // function that creates a list of an object from the given data table
        public static List<T> CreateListFromTable<T>(DataTable tbl) where T : new()
        {
            // define return list
            List<T> lst = new List<T>();

            // go through each row
            foreach (DataRow r in tbl.Rows)
            {
                // add to the list
                lst.Add(CreateItemFromRow<T>(r));
            }

            // return the list
            return lst;
        }

        // function that creates an object from the given data row
        public static T CreateItemFromRow<T>(DataRow row) where T : new()
        {
            // create a new object
            T item = new T();

            // set the item
            SetItemFromRow(item, row);

            // return 
            return item;
        }

        public static void SetItemFromRow<T>(T item, DataRow row) where T : new()
        {
            // go through each column
            foreach (DataColumn c in row.Table.Columns)
            {
                // find the property for the column
                PropertyInfo p = item.GetType().GetProperty(c.ColumnName);

                // if exists, set the value
                if (p != null && row[c] != DBNull.Value)
                {
                    p.SetValue(item, row[c], null);
                }
            }
        }

        //call stored procedure to get data.
        public static DataSet GetRecordWithExtendedTimeOut(string SPName, params SqlParameter[] SqlPrms)
        {
            DataSet ds = new DataSet();
            SqlCommand cmd = new SqlCommand();
            SqlDataAdapter da = new SqlDataAdapter();
            SqlConnection con = new SqlConnection(connectionString);

            try
            {
                cmd = new SqlCommand(SPName, con);
                cmd.Parameters.AddRange(SqlPrms);
                cmd.CommandTimeout = 240;
                cmd.CommandType = CommandType.StoredProcedure;
                da.SelectCommand = cmd;
                da.Fill(ds);
            }
            catch (Exception ex)
            {
               return ex;
            }

            return ds;
        }
}

Maintenant, le moyen de passer et d'appeler la méthode est ci-dessous.

    DataSet ds = DAL.GetRecordWithExtendedTimeOut("ProcedureName");

    List<YourViewModel> model = new List<YourViewModel>();

    if (ds != null)
    {
        //Pass datatable from dataset to our DAL Method.
        model = DAL.CreateListFromTable<YourViewModel>(ds.Tables[0]);                
    }      

Jusqu'à la date limite, pour beaucoup de mes applications, j’ai trouvé cela comme la meilleure structure pour obtenir des données .

6
Bharat

Vous voudrez peut-être jeter un coup d'œil au code ici . Bien que cela ne réponde pas directement à votre question, vous pouvez adapter les types de classe génériques utilisés pour mapper des classes de données et des objets métier.

De plus, en utilisant générique, vous exécutez le processus de conversion aussi rapidement que possible.

0
ChrisBD