문제

데이터 테이어를 반환하는 데이터 계층 선택 메소드가 있습니다. 비즈니스 계층 방법에서 호출되어 강력하게 입력 된 일반 목록을 반환해야합니다.

내가하고 싶은 것은이 질문이 매우 유사하지만 (와 동일하지는 않지만) :
DataTable을 일반 목록으로 어떻게 변환합니까?

다른 점은 목록에 DataRows 대신 강하게 유형 된 객체를 포함하기를 원한다는 것입니다 (또한 여기에는 LINQ가 아직 없습니다).

나는 성능에 대해 걱정하고있다. 비즈니스 계층 방법은 프레젠테이션 계층에서 호출되며 결과는 사용자에게 표시되도록 반복됩니다. 비즈니스 계층에 추가 반복을 추가하는 것은 매우 낭비적인 것 같습니다. 프레젠테이션을 위해 즉시 다시 수행하므로 가능한 한 빨리 원합니다.

이것은 일반적인 작업이므로 반복해서 반복 할 수있는 좋은 패턴을 찾고 있습니다.

도움이 되었습니까?

해결책

당신은 그 구조를 알고 있습니까? DataTable 그리고 미리 타이핑 된 물체? 대의원을 사용하여 매핑을 수행 할 수 있습니다. 당신이하지 않는다면 (즉, 당신이 아는 것은 Type 및 속성) 동적 멤버 액세스를 가속화하는 방법이 있습니다 (예 : HyperDescriptor).

어느 쪽이든, 반복자 블록을 고려하십시오. 그렇게하면 객체를 두 번째로 버퍼링 할 필요가 없습니다. 물론, 당신이 작은 행산 만 다루는 경우 이것은 문제가되지 않습니다.

그 점을 명확히 할 수 있습니까? 더 자세한 내용을 추가 할 수 있습니다 ...

가장 간단하게, 무엇이 잘못되었는지 :

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]));
}

(위의 문제는 올바른 접근 방식을 조종 할 수 있습니다 ...)

다른 팁

위의 샘플의 문제는 매우 느리다는 것입니다. 나는 약 400 행의 데이터 가능을 가지고 있으며이 변환은 5 초 또는 6 초가 걸립니다!

그것은 꽤 일반적인 작업처럼 보이므로 여기에 더 성능적인 솔루션이있는 사람을 보지 못한 것에 놀랐습니다.

* 업데이트!! *킥을 위해서는 데이터 가능을 반복하는 대신 LINQ를 사용하여 목록에 추가하는 대신 LINQ를 사용하는 것을 시도 할 것이라고 생각했습니다. 다음은 내가 한 일입니다.

   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();

첫 번째 방법 (각 행을 통해 반복)은 5.3 초가 걸렸으며 LINQ를 사용하는 방법은 1.8 초가 걸렸습니다!

어쨌든 Datarows를 반복하여 객체로 변환해야하지만 어쨌든 Datarows 모음을 취하고 모든 AT 대신 요청시 객체 유형으로 변환하는 생성자가있는 사용자 정의 컬렉션을 작성할 수 있습니다. 한 번.

구현하는 사용자 정의 컬렉션을 정의한다고 가정 해보십시오 IList<T>. 그런 다음 두 개의 내부 필드가있을 수 있습니다. List<T>. 그만큼 List<T> Datarows 모음의 길이로 초기화되지만 널 값으로 초기화됩니다.

이제 인덱서에서 확인할 수 있습니다 List<T> 해당 인덱스에 값이 포함되어 있지 않으면 유용한 수단을 사용하여 객체를 만들 수 있으며 반환하기 전에 저장할 수 있습니다.

이것은 요청이 요청 될 때까지 객체의 생성을 연기하고 요청 된 객체 만 생성 할 것입니다.

당신의 객체는 아마도 Datarow를 취하는 생성자가 필요할 것입니다. 그렇지 않으면 그것들을 만들려면 어떤 종류의 공장이 필요하지만, 그것은 또 다른 주제입니다.

간단한 콘솔 앱에서 더 많은 사용자 - 마크의 대답에 대한 친근감을 제공하기 위해 :

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();
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top