2009-11-10 3 views
3

일반 목록을 만들고 일부 개체로 채 웁니다. 그런 다음 DataGridView에서 사용하기 위해 DataTable로 변환하기 전에 언급 한 List. 문제는 DataRow가있는이 격자에서 Row를 얻고 싶을 때입니다. 이걸 내 객체로 다시 변환하려고했지만 어떻게해야할지 확신하지 못했습니다. 어쩌면 몇 가지 예를들 수 있습니까?DataRow를 개체로 변환

class MyObject 
{ 
    public string Foo { get; set; } 
    public int Foo { get; set; } 
} 

당신은 그런 일 할 수있는 :

using System.Data.DataSetExtensions; 

... 

List<MyObject> list = (from row in table.AsEnumerable() 
         select new MyObject 
         { 
          Foo = row.Field<string>("foo"), 
          Bar = row.Field<int>("bar") 
         }).ToList(); 
+0

코드의 비트가 도움이 될 것입니다 ... –

답변

9

을 가정 정의, 클래스 MyObject을 사용하고 또는 "ORM"(Linq-to-SQL 또는 NHibernate와 같은 객체 관계형 매퍼 -이 도구가하는 일과 정확히 같은 작업)을 사용하지 않으므로 직접 수행해야합니다. 도메인 객체 모델에 DataRow를 변환

정말 꽤 지루한 코드 :

public Customer ConvertRowToCustomer(DataRow row) 
{ 
    Customer result = new Customer(); 

    result.ID = row.Field<int>("ID"); 
    result.Name = row.Field<string>("CustomerName"); 
    ..... // and so on 

    return result; 
} 

여기에 가장 큰 도전이 견고한 가능한 모든 오류를 처리 (또는 방지) (필드의 존재처럼하고있다 NULL 등).

도메인 모델 개체 유형에 DataRow을 매개 변수로 사용하여 생성자를 생성하는 새 생성자를 만드는 방법이 있습니다.

마크

11

글쎄, 당신은 할 수 없습니다 다음과 같이

감사

+0

ORM을 제안하는 +1. –

+0

고마워, 변환 할 여러 유형이있을 때 이것을 사용할 수 있습니까? 예를 들어 하나의 DataTable에 고객 데이터가있는 레코드와 주소가있는 다른 레코드가 있습니까? 리플렉션을 사용해야합니까? – arek

+0

물론 리플렉션을 사용하여 모든 유형에 대해이 방법을 일반화 할 수 있으며 Reflection.Emit을 사용하여 동적 어셈블리를 생성 한 다음 컬렉션에 지연로드를 추가 할 수있는 리플렉션으로 인해 저하 된 성능을 더욱 향상시킬 수 있습니다. 당신이 사람들이 이미 이러한 문제들에 대해 가르치고 NHibernate, Entity Framework 같은 ORM을 발명했다는 것을 이해할 날 ...이미 존재하고 자유롭게 사용할 수있는 것에 노력을 기울 였음을 깨닫게 될 것입니다. –

1

왜 단지는 바인딩 <로 물건을 올려 놓지>보다는 목록 <>? 그런 다음 DataTable로 변환을 건너 뛰고 다시 운동 할 수 있습니다. 개체에 INotifyPropertyChanged을 구현해야하지만 BindingList 내부에 있으면 DataGrid의 변경 내용이 기본 개체에 자동으로 적용됩니다.

, 또는는 바인딩 <에서 상속>과 내부의 정렬 기능을 구현하여 열 머리글을 클릭에 수동으로 목록을 정렬 중 하나에 의해 처리 될 수 정렬 - 필요없이 코드 - 자동으로 헤더를 클릭하여 목록을 정렬합니다.

0

요즘에는 ORM을 사용하는 것이 더 쉽습니다.

public static class MapperExtensionClass 
{ 

     public static IEnumerable<MyClassType> ToMyClassTypeEnumerable(this DataTable table) 
     { 
      return table.AsEnumerable().Select(r => r.ToMyClassType()); 
     } 

     public static MyClassType ToMyClassType(this DataRow row) 
     {    
      return row.ToObject<MyClassType>(); 
     } 

     public static T ToObject<T>(this DataRow row) where T: new() 
     { 
      T obj = new T(); 
      foreach (PropertyInfo property in typeof(T).GetProperties()) 
      { 
       if (row.Table.Columns.Contains(property.Name)) 
       { 
        property.SetValue(obj, property.PropertyType.ToDefault(row[property.Name])); 
       } 
      } 

      return obj; 
     } 


     public static object ToDefault(this Type type, object obj) 
     { 
      if (type == null) 
       throw new Exception("Customized exception message"); 

      var method = typeof(MapperExtensionClass) 
       .GetMethod("ToDefaultGeneric", BindingFlags.Static | BindingFlags.Public); 

      var generic = method.MakeGenericMethod(type); 

      return generic.Invoke(null, new object[] { obj });    
     } 

     public static T ToDefaultGeneric<T>(object obj) 
     { 
      if (obj == null || obj == DBNull.Value) 
      { 
       return default(T); 
      } 
      else 
      { 
       return (T)obj; 
      } 
     } 
} 

또한 기억해야한다 : 당신은 구식을 사용하고 여전히한다면 다음과 같이 반사 및 일반적인 방법과 람다의 약간을 사용하여 당신을 위해 일을 할 수있는 아주 쉽게 확장 클래스로 갈 수있다 GridView 개체는 많은 데이터 원본 유형을 바인딩 할 수 있습니다. 따라서 당신이 무엇을 가지고 가야하는지에 대한 설계 시점에서의 결정입니다.

관련 문제