2011-05-09 67 views
1

我很新的LINQ,我試圖找出如何實現以下目標:LINQ反射的WinForms

目前,我有了一個DataRow的,因爲它的成員之一鹼形式的WinForms項目。我有幾個派生的表單根據DataTable中的數據填充DataRow(SQL查詢結果)。派生表單上的控件也使用數據中的值填充。當單擊派生窗體上的保存按鈕時,基本窗體中的DataRow會更新,然後派生窗體通過DataAdapter更新數據庫。

我想用linqs所以我試圖實現使用LINQ通過下面這個功能,以取代所有的SQL命令:

我創造了我的LINQ查詢在派生形式和基本結果分配給對象形成。我將基礎表單中的對象轉換爲Linq查詢的類類型,並使用反射來填充派生表單上的所有控件。單擊保存按鈕時,我更新對象,但我無法更新數據庫。

我無法解決的問題是如何在更新對象後更新數據庫。此時我沒有用於linq查詢的數據上下文。

我在linq查詢中使用了一個SQL函數,所以我不得不爲這些值創建一個單獨的類,因爲我得到了一個匿名類型的錯誤。我可能在這裏錯過了一些東西。

任何幫助將不勝感激,因爲我真的是如何清潔linq代碼。

編輯(布拉德的編輯複製到托馬斯的回答):

這裏有3個步驟,我的代碼。

步驟1 - 獲取數據的記錄燎從數據庫

private void GetDatabaseDetailData() 
{ 
_db = new PriorityDataContext(); 

DetailData = (from db in _db.tblDatabases 
       where db.DatabaseID == Id 
       select db).SingleOrDefault(); 



DeveloperData = (from db in _db.tblDatabases 
       where db.DatabaseID == Id 
       select new DeveloperInfo 
       { 
        DeveloperName = _db.func_get_employee_name(db.Developer) 
       }).SingleOrDefault(); 

} 

步驟2 - 填充所有控件衛生組織名對象存在。 DetailData對象被轉換爲傳遞給此方法的特定類型。爲簡潔起見,所有代碼都未顯示。

protected virtual void PopulateDetailControlsA(List<Control> controlContainers, string srcDataTableName) 
    { 
     Object data = null; 
     Type type = null; 
     switch (srcDataTableName) 
     { 
      case "tblDatabases" : 
       type = typeof(tblDatabase); 
       data = (tblDatabase)DetailData; 
       break; 
     } 

     if (type != null) 
     { 
      var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance); 

      foreach (var controlContainer in controlContainers) 
      { 
       foreach (var propertyInfo in properties) 
       { 
        if (!ControlExists(controlContainer, propertyInfo.Name)) continue; 

        var txtControl = controlContainer.Controls[propertyInfo.Name] as ExtendedTextBox; 
        if (txtControl != null) 
        { 
         try 
         { 
          var value = propertyInfo.GetValue(data, null).ToString(); 

          if (propertyInfo.Name == "row_oper_name" || propertyInfo.Name == "row_last_chng_oper_name") 
          { 
           txtControl.Text = RowOperatorData.RowOperatorName; 
           txtControl.ValueMember = propertyInfo.GetValue(data, null).ToString(); 
          } 
          else 
           txtControl.Text = value; 
         } 
         catch (NullReferenceException) 
         { 
         } 
         continue;........... 

步驟3 - 嘗試和回數據庫保存更改派生而來。

private void SaveData() 
{ 
      try 
     { 
      _db.SubmitChanges(); 
     } 
     catch (Exception sqlException) 
     { 

     } 
} 

我真的不清楚聽到的是如何將結果存儲在基本形式設置,這樣我可以使用相同的代碼爲許多不同的查詢。 DataRow工作得很好,因爲我使用一些代碼來處理超過25個派生表單。

+0

爲什麼不使用LINQtoSQL?它已經有了所有有用的方法。你可以在DataContext上調用SubmitChanges()http://msdn.microsoft.com/en-us/library/system.data.linq.datacontext.aspx – Bazzz 2011-05-09 12:11:12

+0

是的,我正在使用LinqtoSQL,它一切正常。我的問題是我不知道如何更新基表中的數據庫,因爲此時我沒有用於獲取查詢結果的原始DataContext。我試圖把DataContext作爲派生表單的成員,但是這不起作用。 – Brad 2011-05-09 12:13:57

+0

我將您的編輯轉移到Tomas的問題答案中。 – Brian 2011-05-09 17:40:29

回答

0

如果我的理解正確,您可以在派生形式中創建DataContext,然後使用它來編寫一些查詢(以派生形式)。爲了能夠更新數據庫,您的查詢必須返回從表中獲得的實體(即,select子句應該只返回實體)。例如:

DataContext db = // ... 
var q = from p in db.Things 
     where p.Some > 10 select p; 

如果再修改的實體,您可以使用db.SubmitChanges(),存儲改變(對實體對象進行)到數據庫中。爲此,您需要原始的db值。

在您的方案中,您需要在派生形式中存儲DataContext(作爲字段)。如果您需要從基礎表單執行更新,那麼我建議您定義一個虛擬方法:

// Base form 
protected abstract void UpdateDatabase(); 

// Derived from with field 'db' storing 'DataContext' 
protected override void UpdateDatabase() { 
    db.SumbitChanges(); 
} 
+0

@布拉德:你應該編輯你的問題,而不是這個答案。 – SLaks 2011-05-09 16:14:08