2009-11-13 45 views
2

這似乎是我正在做的一件非常基本的事情,但我正在試圖讓它工作。如何使用TableAdapter更新DataSet的單個表,而無需對錶名進行硬編碼?

我的情況是這樣的:我有一個包含大量查找表的項目,並且我在所有這些查找表中表示了一個類型化的DataSet,其中包含每個查找的TableAdapters。我爲這些查找表設計了一個編輯器,可以一次編輯其中的一個。我的前端是用VB和WinForms編寫的,後端是一個SOAP Web服務;我可以成功地將更改傳遞給DataSet返回到Web服務,但無法找到使用TableAdapter更新已更改的單個表的方法。

我想要做的是通過將表的名稱與DataSet一起發送回Web服務,然後使用動態名稱引用TableAdapter,爲更新的DataTable實例化適當的TableAdapter。實例化一個TableAdapter的正常方式是這樣的:

Dim ta As New dsLookupsTableAdapters.tlkpMyTableTableAdapter 

我想要做的就是這個,當然這是行不通的:

strTableName = "tlkpMyTable" 
Dim ta As New dsLookupsTableAdapters(strTableName & "TableAdapter") 

有什麼辦法來實現這一目標,還是我完全採取錯誤的做法?我的另一種選擇是爲每個表編寫單獨的代碼,我寧願避免!

回答

2

您可以使用激活從其字符串名稱創建的TableAdapter的實例,就像你想要的:

object adapter = Activator.CreateInstance(Type.GetType("My.Namespace.MyDataSetTableAdapters." + myTable.Name + "TableAdapter")); 

然後,因爲TableAdapter的沒有一個通用的接口,你應該使用反射來調用它的更新方法:

adapter.GetType().GetMethod("Update").Invoke(adapter, null); 

http://msdn.microsoft.com/en-us/library/system.type.getmethod.aspx

這是來自記憶,但大致足夠接近。您也可以使用GetProperty獲取連接屬性並根據需要進行設置。

+0

因爲它是VB.NET,所以避免反射並使用CallByName(適配器,「更新」,CallType.Method,Nothing) – AMissico

+0

感謝球員們,我們做到了。對不起,我花了很長時間纔回到這個問題 - 我一直忙於更緊急的項目其他方面。不幸的是,我似乎無法接受答案 - 任何想法爲什麼? – Billious

+0

嗯 - 只是發現在賞金到期後你不能接受答案,這有點煩人。伊利亞,你的回答是我會接受的答案,但是在賞金到期後纔得到答覆 - 無論如何,謝謝! – Billious

1

給定(字符串)類型名稱,在運行時創建類型非常簡單。

下面是一個自包含的VB類,它說明了一種方法:使用System.Activator.CreateInstance使用類型名稱的字符串表示形式創建類型的實例。然後,您可以將其轉換爲DataAdapter基類,並像其他任何DataAdapter一樣使用它。

Public Class dsLookupsTableAdapters 

    Public Function CreateInstance(ByVal strName As String) As Object 
     CreateInstance = Nothing 

     For Each a As System.Reflection.Assembly In System.AppDomain.CurrentDomain.GetAssemblies() 
      Try 
       Dim strAssemblyName As String() = a.FullName.Split(New Char() {","c}) 
       Dim strNameTemp As String = strAssemblyName(0) & "." & strName 
       Dim instance As Object = System.Activator.CreateInstance(a.FullName, strNameTemp) 
       If instance IsNot Nothing Then 
        Dim handle As System.Runtime.Remoting.ObjectHandle 
        handle = CType(instance, System.Runtime.Remoting.ObjectHandle) 
        Dim o As Object = handle.Unwrap() 
        CreateInstance = o 
        Exit For 
       End If 
      Catch ex As System.Exception 
       Continue For ' ignore exception, means type isn't there 
      End Try 
     Next 
    End Function 


    Public Class tlkpMyTableTableAdapter 
     Inherits System.Data.Common.DataAdapter 

    End Class 


    Public Sub Test() 
     ' define type name. note that, in this sample, tlkpMyTableTableAdapter is a nested 
     ' class and dsLookupsTableAdapters is the containing class, hence the "+". If, however, 
     ' dsLookupsTableAdapters is a namespace, replace the "+" with a "." 
     Dim typeName As String = "dsLookupsTableAdapters+tlkpMyTableTableAdapter" 
     Dim adapter As System.Data.Common.DataAdapter 
     Dim o As Object = CreateInstance(typeName) 
     adapter = CType(o, System.Data.Common.DataAdapter) 

    End Sub 

End Class 
+0

對不起,不能早點回復你 - 我們現在正在搬家,我還沒有機會嘗試!將盡快這樣做。 – Billious

+0

沒問題。僅供參考,您的賞金將在半小時內過期,所以如果您想要測試此代碼,您可能很快就會這麼做。:-) –

+0

嗨,賈斯汀,只是讓你知道我沒有忘記你 - 我已經試過了代碼,但還沒有得到它的工作(主要是由於我自己的無知,我認爲)。我不得不專注於我的項目的另一部分,但會在本週再次嘗試。 – Billious

1

不知道我100%理解,你的DataSet中有單個DataTable還是每個查詢表有一個DataTable?

無論如何,也許你可以你this approach按查找表過濾嗎?

+0

不,我的DataSet中有多個DataTable(帶有TableAdapter)。加載應用程序時,我使用此DataSet同時將所有查找表加載到內存中。但是,在更新查找表時,我希望能夠通過只將修改發送回給定的表並使用適當的TableAdapter用於更新語句來完成此操作。 – Billious

1

如果您使用的是VB.Net 2008,請使用tableadaptermanager(http://msdn.microsoft.com/en-us/library/bb384426.aspx)。我認爲這將是更容易編寫針對:)

韋德

+0

對不起,雖然我使用的是VS2008,但我只爲.NET Framework 2.0版編寫的服務器,而TableAdapterManager僅在v3.5及更高版本中可用。雖然會是一個有用的工具! – Billious

相關問題