2017-08-27 16 views
2

別のシステムからの入力として受け取るDataTableから「IEnumerable」を生成する必要があります。次のコードは、ASP.NET 4.6.1で機能しました。DataTableをIEnumerableに変換する<T>(ASP.NET Core 2.0)

public static IEnumerable<UserAssignmentDto> StaffAssignmentsUsingStoredProcedure(System.Data.DataTable dataTable) 
    { 
     var data = dataTable.AsEnumerable().Select(row => 
      new UserAssignmentDto 
      { 
       Id = ((string)row["AssignmentNumber"]), 
       Position = (string) row["EsrPositionTitle"], 

      }); 

     return data; 
    } 

ただし、 'DataTable'には、ASP.NET Core 2.0で 'AsEnumerable'の定義が含まれなくなりました。

私が必要とする 'IEnumerable'を生成する最も効率的な方法は何でしょうか?

+0

は、forループを使用してDataTableの行を反復処理し、 –

+0

のIEnumerableを水和あなたは水和物で何を意味するか私を見ることができますか? –

+0

「dataTable.Rows.Select(...);」と言うだけでいいですか? "item"がオブジェクトの場合、OfType <> '' dataTable.Rows.OfTypeを追加できます。().Select(...); '' –

答えて

2

あなたができる最も効率的な方法の1つは、LINQの代わりにforループを使用して、DataTable行を繰り返し実行し、IEnumerable<UserAssignmentDto>メソッドの戻り値を「手作業で」ビルド/ハイドレートすることです。

DataTableは.NET Core 2.0で列挙子を実装していないため、「通常の」forループを使用して行を反復処理する必要があります。 DataTableが.NET Core 2.0でIEnumerableを実装していないため、foreachは使用できません。

public static IEnumerable<UserAssignmentDto> StaffAssignmentsUsingStoredProcedure(System.Data.DataTable dataTable) 
{ 
    var retList = new List<UserAssignmentDto>(); 

    for(int i = 0; i < dataTable.Rows.Count; i++) 
    { 
      var row = dataTable.Rows[i]; 

      var temp = new UserAssignmentDto(){ 
       Id = row["AssignmentNumber"], 
       Position = row["EsrPositionTitle"] 
      }; 

      retList.Add(temp);  
    } 

    return retList; 
} 
+0

List を初期化する必要があります。また、エラーが発生しています。CS1579 \t 'DataTable'に 'GetEnumerator'のパブリック定義が含まれていないため、foreach文が 'DataTable'型の変数で操作できない –

+0

@RoddyBalkan okエラーを修正するための回答を更新しました –

+0

@RoddyBalkan List はすでに初期化されています。このコード行は次のとおりです。var retList = List (); –

1

効率はユースケースによって異なります。あなたが全体の結果を必要とするなら、Briansの答えは良いです。リストの容量をあらかじめ割り当てておくことで、サイズ変更や配列への変更を避けることで、改善することができますが、一般的には良いことです。リストまたは配列を返して、明示的に表示するようにしたいと思いますが、それは私の個人的な選択です。 DataTableは呼び出された瞬間に状態を保存します。必要なものによっては良いか悪いかがわかります。

あなたはすべての項目を必要としないか、多分あなたは、まったくのIEnumerableを列挙しません、本当の列挙子を構築するために、より効率的かもしれチャンスがある場合:

public static IEnumerable<UserAssignmentDto> StaffAssignmentsUsingStoredProcedure(System.Data.DataTable dataTable) 
     { 
      foreach (DataRow row in dataTable) 
      { 
       yield return new UserAssignmentDto() 
       { 
        Id = row["AssignmentNumber"], 
        Position = row["EsrPositionTitle"] 
       };    
      } 
     } 

しかし、それは最速のオプションではありませんがまだ。あなたは新しいオブジェクトを得るたびに割り当てることを避けるかもしれません。毎回同じオブジェクトを返すことができ、それに応じてプロパティを設定するだけです。このようなIEnumerableからのオブジェクトを将来使用するために格納することはできないという明らかな欠点がありますが、時にはそれを必要としないこともあります。最も効率的な程度

public static IEnumerable<UserAssignmentDto> StaffAssignmentsUsingStoredProcedure(System.Data.DataTable dataTable) 
     { 
      UserAssignmentDto ret = new UserAssignmentDto(); 
      foreach (DataRow row in dataTable) 
      { 
       ret.Id = row["AssignmentNumber"]; 
       ret.Position = row["EsrPositionTitle"]; 
       yield return ret; 
      } 
     } 
0

ないが、代替のために、あなたはSelectメソッドを使用することができます

DataRow[] rows= dataTable.Select(); 

をそして今、あなたは、行のIEnumerableをを持っています。 この方法は、誰かを助けることがあります。

public static List<T> ConvertDataTableToGenericList<T>(DataTable dt) 
{ 
    var columnNames = dt.Columns.Cast<DataColumn>() 
      .Select(c => c.ColumnName) 
      .ToList(); 

    var properties = typeof(T).GetProperties(); 
    DataRow[] rows= dataTable.Select(); 
    return rows.Select(row => 
    { 
      var objT = Activator.CreateInstance<T>(); 
      foreach (var pro in properties) 
      { 
       if (columnNames.Contains(pro.Name)) 
        pro.SetValue(objT, row[pro.Name]); 
      } 

      return objT; 
    }).ToList(); 
} 
関連する問題