Foi útil?

Solução

Você conhece a estrutura do DataTable eo objeto digitado antes do tempo? Você poderia usar um delegado para fazer o mapeamento. Se não o fizer (ou seja, tudo que você sabe é um Type e propriedades), existem formas de acelerar o acesso de membros dinâmica (como HyperDescriptor).

De qualquer forma, considere um bloco de iterator; Dessa forma, você não tem para tamponar a objetos toda uma segunda vez; Claro, se você está lidando apenas com rowcounts smallish isso não é um problema.

Você pode esclarecer qualquer um desses pontos? Posso adicionar um detalhe muito mais ...

No mais simples, o que está errado com:

DataTable table = new DataTable {
    Columns = {
        {"Foo", typeof(int)},
        {"Bar", typeof(string)}
     }
};
for (int i = 0; i < 5000; i++) {
    table.Rows.Add(i, "Row " + i);
}

List<MyType> data = new List<MyType>(table.Rows.Count);
foreach (DataRow row in table.Rows) {
    data.Add(new MyType((int)row[0], (string)row[1]));
}

(os problemas no acima pode orientar o caminho certo ...)

Outras dicas

O problema com o exemplo acima é que é terrivelmente lento. Eu tenho um DataTable com cerca de 400 linhas e esta conversão leva uma boa 5 ou 6 segundos!

Ele faz parecer uma tarefa comum muito, por isso estou surpreso de não ver alguém aqui com uma solução de maior performance.

* Atualização !! * Apenas por diversão, eu pensei que eu tentaria converter usando LINQ em vez de iteração através do DataTable e adicionar a minha lista. O seguinte é o que eu fiz:

   List<MyObject> returnList = new List<MyObject>();

   MyDataTable dtMyData = new MyTableAdapter().GetMyData();

   returnLists = (from l in dtMyData
                 select new MyObject
                 {
                    Active = l.IsActive,
                    Email = l.Email,
                    //...
                    //About 40 more properties
                    //...
                    ZipCode = l.Zipcode
                  }).ToList();

O primeiro método (iteração através de cada linha) levou 5,3 segundos eo método usando LINQ levou 1,8 segundos!

Você precisará percorrer os DataRows e convertê-los em seus objetos em algum momento de qualquer maneira, mas você poderia escrever uma coleção personalizada com um construtor que leva uma coleção de DataRows e que converte cada item em seu tipo de objeto, quando solicitado, em vez de uma só vez.

Say você define sua coleção personalizada que implementa IList<T>. Ele poderia, então, ter dois campos internos - uma referência à coleção de DataRows e uma List<T>. O List<T> iria ser inicializado para o comprimento da coleção de DataRows mas com valores nulos.

Agora, no indexador você pode verificar se o List<T> contém um valor nesse índice e se não é possível criar o objeto usando qualquer meio seria útil e armazená-lo lá antes de devolvê-lo.

Este seria adiar a criação de seus objetos até que eles foram solicitados e você só iria criar os objetos que foram solicitados.

Seus objetos provavelmente precisa de um construtor tomar um DataRow ou você iria precisar de algum tipo de fábrica para criá-los, mas isso é outro assunto.

Apenas para proporcionar mais algum usuário - simpatia para a resposta de Mark em um aplicativo de console simples:

class Program
{
    static void Main(string[] args)
    {
        //define a DataTable obj
        DataTable table = new DataTable
        {
            Columns = {
            {"Foo", typeof(int)},
            {"Bar", typeof(string)}
         }
        };
        //populate it the DataTable 
        for (int i = 0; i < 3; i++)
        {
            table.Rows.Add(i, "Row " + i);
        }

        List<MyType> listWithTypedObjects= new List<MyType>(table.Rows.Count);
        foreach (DataRow row in table.Rows)
        {
            listWithTypedObjects.Add(new MyType((int)row[0], (string)row[1]));
        }

        Console.WriteLine(" PRINTING THE POPULATED LIST ");
        foreach (MyType objMyType in listWithTypedObjects)
        {
            Console.Write(" I have object of the type " + objMyType.ToString() + " => " );
            Console.Write(" with Prop1OfTypeInt " + objMyType.Prop1OfTypeInt.ToString() + " , ");
            Console.WriteLine(" with Prop1OfTypeInt " + objMyType.Prop2OfTypeString.ToString() + "  "); 
        }

        Console.WriteLine(" \n \n \n HIT A KEY TO EXIT THE PROGRAM ");
        Console.ReadKey();
    }
}

class MyType {

    public int Prop1OfTypeInt { get; set; }
    public string Prop2OfTypeString { get; set; } 

    /// <summary>
    /// Note the order of the passed parameters is important !!!
    /// </summary>
    public MyType( int prop1OfTypeInt , string prop2OfTypeString)
    {
        this.Prop1OfTypeInt = prop1OfTypeInt;
        this.Prop2OfTypeString = prop2OfTypeString; 

    }
}
public partial class issuereceive_manageroffice_bal
{
    public int issue_id{get;set;}
    public string process{get;set;}
    public DateTime issue_date{get;set;}
    public TimeSpan issue_time{get;set;}
    public string eg_no{get;set;}
    public string lotno{get;set;}
    public string clarity{get;set;}
    public string sieves{get;set;}
    public string shape{get;set;}
    public double issue_carat{get;set;}
    public int issue_pieces{get;set;}
    public int receive_pieces{get;set;}
    public double receive_carat{get;set;}
    public int kp_pieces{get;set;}
    public decimal kp_carat{get;set;}
    public double loss{get;set;}
    public string issue_manager{get;set;}
    public string issue_by{get;set;}
    public string receive_by{get;set;}
    public int status{get;set;}
    public DateTime receive_date{get;set;}
    public string receive_time{get;set;}
    public int factory_id{get;set;}

}


List<issuereceive_manageroffice_bal> issue_receive_list = new List<issuereceive_manageroffice_bal>();
issue_receive_list =
      (from DataRow dr in DataTable.Rows
      select new issuereceive_manageroffice_bal()
           {
               issue_id = 0,
               issue_time = TimeSpan.Parse("0"),
               receive_time = null,
               shape = null,
               process = dr["process"].ToString(),
               issue_date = Convert.ToDateTime(dr["issue_date"]),
               eg_no = dr["eg_no"].ToString(),
               lotno = dr["lotno"].ToString(),
               clarity = dr["clarity"].ToString(),
               sieves = dr["sieves"].ToString(),
               issue_carat = dr["issue_carat"].ToString() != "" ? double.Parse(dr["issue_carat"].ToString()) : 0,
               issue_pieces = dr["issue_pieces"].ToString() != "" ? int.Parse(dr["issue_pieces"].ToString()) : 0,
               receive_carat = dr["receive_carat"].ToString() != "" ? double.Parse(dr["receive_carat"].ToString()) : 0,
               kp_pieces = dr["kp_pieces"].ToString() != "" ? int.Parse(dr["kp_pieces"].ToString()) : 0,
               kp_carat = dr["kp_carat"].ToString() != "" ? decimal.Parse(dr["kp_carat"].ToString()) : 0,
               loss = dr["loss"].ToString() != "" ? double.Parse(dr["loss"].ToString()) : 0,
               issue_manager = dr["lotno"].ToString(),
               issue_by = dr["issue_by"].ToString(),
               receive_by = dr["receive_by"].ToString(),
               status = dr["status"].ToString() != "" ? int.Parse(dr["status"].ToString()) : 0,
               receive_date = Convert.ToDateTime(dr["receive_date"]),
               factory_id = dr["factory_id"].ToString() != "" ? int.Parse(dr["factory_id"].ToString()) : 0,

           }).ToList();
scroll top