2010-04-16 87 views
1

我當前的項目是從OleDbDatabase和.CSV文件獲取信息,並將其全部放入更大的OleDbDatabase從OleDb數據庫讀取/寫入數據表LINQ

我目前從兩個.CSV文件中讀取所有需要的信息,並將OleDbDatabase轉換爲DataTables ....在哪裏變得毛茸茸的是將所有信息寫回另一個OleDbDatabase。

現在我目前的方法是做這樣的事情:

OleDbTransaction myTransaction = null; 

    try 
    { 
     OleDbConnection conn = new OleDbConnection("PROVIDER=Microsoft.Jet.OLEDB.4.0;" + 
                "Data Source=" + Database); 
     conn.Open(); 
     OleDbCommand command = conn.CreateCommand(); 
     string strSQL; 

     command.Transaction = myTransaction; 

     strSQL = "Insert into TABLE " + 
       "(FirstName, LastName) values ('" + 
       FirstName + "', '" + LastName + "')"; 

     command.CommandType = CommandType.Text; 
     command.CommandText = strSQL; 

     command.ExecuteNonQuery(); 

     conn.close(); 

    catch (Exception) 
     { 
      // IF invalid data is entered, rolls back the database 
      myTransaction.Rollback(); 
     } 

當然,這是很基本的,我使用的是SQL命令提交我的交易連接。我的問題是我可以做到這一點,但我有大約200個字段需要插入幾個表。如果這是唯一的出路,我願意做這項工作。但我覺得有一個更簡單的方法。 LINQ中有什麼可以幫助我解決這個問題嗎?

回答

5

如果DataTable中的列名與目標表中的列名完全匹配,那麼您可以使用OleDbCommandBuilder(警告:我還沒有測試過)。如果源數據表的數據類型與目標表的數據類型不匹配(例如,如果源列數據類型都是字符串),則可能遇到問題的一個方面。

編輯 我以多種方式修改了我的原始代碼。首先,我切換到在DataTable上使用Merge方法。這允許我跳過在循環中使用LoadDataRow

using (var conn = new OleDbConnection(destinationConnString)) 
{ 
    //query off the destination table. Could also use Select Col1, Col2.. 
    //if you were not going to insert into all columns. 
    const string selectSql = "Select * From [DestinationTable]"; 

    using (var adapter = new OleDbDataAdapter(selectSql, conn)) 
    { 
     using (var builder = new OleDbCommandBuilder(adapter)) 
     { 
      conn.Open(); 

      var destinationTable = new DataTable(); 
      adapter.Fill(destinationTable); 

      //if the column names do not match exactly, then they 
      //will be skipped 
      destinationTable.Merge(sourceDataTable, true, MissingSchemaAction.Ignore); 

      //ensure that all rows are marked as Added. 
      destinationTable.AcceptChanges(); 
      foreach (DataRow row in destinationTable.Rows) 
       row.SetAdded(); 

      builder.QuotePrefix = "["; 
      builder.QuoteSuffix= "]"; 

      //forces the builder to rebuild its insert command 
      builder.GetInsertCommand(); 
      adapter.Update(destinationTable); 
     } 
    } 
} 

加成另一種解決方法是使用一個框架像FileHelpers讀取CSV文件,並張貼到你的數據庫。它確實有一個OleDbStorage DataLink用於發佈到OleDb源文件中。請參閱SqlServerStorage InsertRecord示例以瞭解如何(最終將OleDbStorage替換爲SqlServerStorage)。

+0

目前我有一個類似於此的方法,但工作稍好。這似乎仍然sl,不馴,但它與我所遇到的解決方案類似。我試圖找出一些更清潔的東西。 – jsmith 2010-04-20 13:41:40

+0

@jsmith - 你爲什麼認爲它馬虎?如果不使用外部庫,「更乾淨」的解決方案會是什麼樣子?任何其他方法都需要循環遍歷列,構建插入語句,然後循環遍歷列和行並執行插入操作。海事組織,這是非常麻煩,需要更多的代碼。我已更新我的帖子,建議您可能會發現「清潔」的FileHelpers。它當然應該使解析CSV更容易。 – Thomas 2010-04-20 14:51:20

+0

@托馬斯 - 我不知道爲什麼我認爲它馬虎。 「這似乎馬虎」是我說的。我不知道是否是這樣,這就是我問這個問題的原因。如果我知道一個「更清潔」的解決方案,我不會要求一個。我只是試圖找到最好的解決方案。現在,就是這樣,但它只是覺得它可能會更好。不過,我覺得我錯了。 – jsmith 2010-04-20 14:54:52

0

這聽起來像你有很多.mdb和.csv,你需要合併成一個單一的.mdb。這個答案正在運行,並且你有SQL Server可用。如果你不這樣做,那麼考慮下載SQL Express。

使用SQL Server充當多個數據源和目標數據存儲之間的代理。將每個數據源腳本作爲插入到SQL Server持有表中的腳本。將所有數據加載到保留表中時,執行最終壓入目標Access數據存儲。

考慮採用以下步驟:

  • 在SQL Server上,創建臨時表爲導入CSV數據。

CREATE TABLE CsvImport (客戶ID SMALLINT, 姓氏VARCHAR(40), 出生日期SMALLDATETIME)

  • 創建一個存儲過程,他們的工作將是閱讀給定的CSV文件路徑,並插入到一個SQL Server表。

CREATE PROC ReadFromCSV @CsvFilePath VARCHAR(1000) AS BULK INSERT CsvImport FROM @CsvFilePath - 'C:\ some.csv' WITH ( FIELDTERMINATOR = '', - - 您自己特定的終結應該在這裏 ROWTERMINATOR = '\ n' ) GO

  • 創建一個腳本來調用這個S tored proc 對於您在磁盤上的每個.csv文件。也許一些Excel欺騙或文件系統dir管道命令可以幫助您創建這些語句。


exec ReadFromCSV 'c:\1.csv

  • 對於每個.MDB數據源,創建一個臨時鏈接的服務器。


DECLARE @MdbFilePath VARCHAR(1000); SELECT @MdbFilePath ='C:\ MyMdb1.mdb'; EXEC master.dbo.sp_addlinkedserver @server = N'MY_ACCESS_DB_」,@ srvproduct = N'Access',@提供商= N'Microsoft.Jet.OLEDB.4.0' ,@ DATASRC = @ MdbFilePath

-- grab the relevant data 
--your data's now in the table... 
INSERT CsvImport(CustomerID, 

SELECT [CustomerID] 
    ,[LastName] 
    ,[BirthDate] 
FROM [MY_ACCESS_DB_]...[Customers] 

--remove the linked server 
EXEC master.dbo.sp_dropserver @server=N'MY_ACCESS_DB_', @droplogins='droplogins' 
  • 完成將數據導入該保存表後,請在SQL Server實例中創建鏈接服務器。這是目標數據存儲。 SELECT將數據從SQL Server轉換爲Access。


EXEC master.dbo.sp_addlinkedserver @server = N'MY_ACCESS_TARGET '@ srvproduct = N'Access',@提供商= N'Microsoft.Jet.OLEDB.4.0' ,@ DATASRC =' C: \ Target.mdb'

INSERT INTO [MY_ACCESS_TARGET]...[Customer] 
      ([CustomerID] 
      ,[LastName] 
      ,[BirthDate]) 
SELECT Customer, 
     LastName, 
     BirthDate 
FROM  CsvImport