簡體   English   中英

如何用LINQ的結果填充DataTable?

[英]How to fill a DataTable with the result of a LINQ?

我有一個調用存儲過程的方法。 它使用員工編號作為參數來檢索特定員工的數據,然后用結果填充數據表。

protected DataTable CreateDT(string empNo)
        {
            DataTable dataTable = null;
            try
            {
                SqlCommand cmd = new SqlCommand("FIND_EMPLOYEE_BY_EMPNO", pl.ConnOpen());
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.Add(new SqlParameter("@EMPNO", (object)empNo));
                SqlDataAdapter da = new SqlDataAdapter(pl.cmd);
                dataTable = new DataTable("dt");
                da.Fill(dt);
            }
            catch (Exception x)
            {
                MessageBox.Show(x.GetBaseException().ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                pl.MySQLConn.Close();
            }
            return dt;
        }

我要完成的工作是將此代碼轉換為LINQ,但是我不知道如何獲得結果並將其填充到我的數據表中。 見下文:

替代文字http://a.imageshack.us/img706/9017/testki.jpg

protected DataTable CreateDT(string empNo)
        {
            DataTable dataTable = null;
            try
            {
                DataClasses1DataContext dataClass1 = new DataClasses1DataContext();
                // I tried to cast it to DataTable, but it doesn't work...
                dataTable = (DataTable)dataClass1.findEmployeeByID(empNo);
            }
            catch (Exception x)
            {
                MessageBox.Show(x.GetBaseException().ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                pl.MySQLConn.Close();
            }
            return dt;
        }

請指導我如何正確執行此操作。

為什么需要精確填寫數據表? 大多數使用數據表的可綁定控件都接受標准LINQ的收集結果所產生的任何基於枚舉的對象。

無論如何,您都必須重構代碼以使用LINQ對象,因此您不妨繼續進行所有更改。 從長遠來看,您會更快樂,因為LINQ比ado.net更易於使用。

但是要回答這個問題,您將不得不遍歷列表並將每個元素插入到數據表中。 像這樣(在本文中找到的代碼示例):

public DataTable LINQToDataTable<T>(IEnumerable<T> varlist)
{
     DataTable dtReturn = new DataTable();

     // column names 
     PropertyInfo[] oProps = null;

     if (varlist == null) return dtReturn;

     foreach (T rec in varlist)
     {
          // Use reflection to get property names, to create table, Only first time, others 
          will follow 
          if (oProps == null)
          {
               oProps = ((Type)rec.GetType()).GetProperties();
               foreach (PropertyInfo pi in oProps)
               {
                    Type colType = pi.PropertyType;

                    if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition()      
                    ==typeof(Nullable<>)))
                     {
                         colType = colType.GetGenericArguments()[0];
                     }

                    dtReturn.Columns.Add(new DataColumn(pi.Name, colType));
               }
          }

          DataRow dr = dtReturn.NewRow();

          foreach (PropertyInfo pi in oProps)
          {
               dr[pi.Name] = pi.GetValue(rec, null) == null ?DBNull.Value :pi.GetValue
               (rec,null);
          }

          dtReturn.Rows.Add(dr);
     }
     return dtReturn;
}

為什么需要返回一個DataTable LINQ的一大優點是您可以使用強類型的集合,而不是字符串鍵的DataTable

protected IEnumerable<Employee> GetEmployee(string empNo)
{
    try
    {
        DataClasses1DataContext dataClass1 = new DataClasses1DataContext();
        // I tried to cast it to DataTable, but it doesn't work...
        return dataClass1.findEmployeeByID(empNo);
    }
    catch (Exception x)
    {
        MessageBox.Show(x.GetBaseException().ToString(), "Error",
                        MessageBoxButtons.OK, MessageBoxIcon.Error);
        return null;
    }
    finally
    {
        pl.MySQLConn.Close();
    }
}

其他一些要點:

  1. 我將從此方法中刪除異常處理,將其放在更高級別。 如果您使用的是WinForms(看來是這樣),我將讓異常一直冒泡到默認的WinForms異常處理程序(將處理程序添加到Application.ThreadException )。
  2. 我還將使DataContext類成為一個成員變量,而不是創建和銷毀每個調用。 這樣做的好處是,如果您在同一個實例上執行多個更新,則可以調用一個Save()並將其全部應用-這導致對服務器的一次調用,而不是對每個服務器的一次調用。

findEmployeeByID最有可能返回IEnumerable<Employee> 考慮到要切換為使用LINQ,實際上應該利用強類型數據並在整個應用程序中使用它們。 因此,更改CreateDT函數的返回類型並相應地調整其余代碼(我假設存儲過程最多返回一個結果):

protected Employee CreateDT(string empNo)
    {

        try
        {
            DataClasses1DataContext dataClass1 = new DataClasses1DataContext();
            // I tried to cast it to DataTable, but it doesn't work...
            return dataClass1.findEmployeeByID(empNo).FirstOrDefault();
        }
        catch (Exception x)
        {
            MessageBox.Show(x.GetBaseException().ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
        finally
        {
           //might need to dispose the context here
        }
        return null;
    }

用法:

 var employee = CreateDT(1234);
 //You can now access members of employee in a typesafe manner
 string name = employee.Name;

編輯更新的代碼-這是您可以重寫舊的DataTable代碼的方法:

 protected void RetrieveEmployee(string empNo) { 
     Employee emp = CreateDT(empNo);// <---- Here 
     txtEmployeeNo.Text = emp.EmployeeNo;
     txtLastName.Text = emp.LastName;
     //....
 }

請注意,缺少數組索引和后綁定列說明符-即dt[0]["EmployeeNo"]變為emp.EmployeeNo必須更安全,更快emp.EmployeeNo容易閱讀。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM