在OleDb数据库LINQ中读取/写入数据表

在OleDb数据库LINQ中读取/写入数据表,linq,datatable,insert,oledb,Linq,Datatable,Insert,Oledb,我当前的项目是从OLEDB数据库和.CSV文件中获取信息,并将其全部放在一个更大的OLEDB数据库中 目前,我已将.CSV文件和OLEDB数据库中需要的所有信息读入数据表。。。。令人毛骨悚然的是将所有信息写回另一个OLEDB数据库 目前我的方法是这样做: OleDbTransaction myTransaction = null; try { OleDbConnection conn = new OleDbConnection("PROVIDER=Mic

我当前的项目是从OLEDB数据库和.CSV文件中获取信息,并将其全部放在一个更大的OLEDB数据库中

目前,我已将.CSV文件和OLEDB数据库中需要的所有信息读入数据表。。。。令人毛骨悚然的是将所有信息写回另一个OLEDB数据库

目前我的方法是这样做:

    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中有什么东西可以帮我解决这个问题吗?

如果DataTable中的列名与目标表中的列名完全匹配,那么您可能可以使用OleDbCommandBuilder警告:我还没有测试这个。您可能遇到的一个问题是源数据表的数据类型与目标表的数据类型不匹配,例如,如果源列数据类型都是字符串

编辑 我以多种方式修改了我的原始代码。首先,我切换到对数据表使用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 );
        }
    }
}

另外,另一种解决方案是使用类似于读取CSV文件并将其发布到数据库中的框架。它确实有一个用于发布到OleDb源的OleDb存储数据链接。请参阅示例以了解最终如何将OleDbStorage替换为SqlServerStorage。

如果DataTable中的列名与目标表中的列名完全匹配,则您可能可以使用OleDbCommandBuilder警告:我尚未测试此功能。您可能遇到的一个问题是源数据表的数据类型与目标表的数据类型不匹配,例如,如果源列数据类型都是字符串

编辑 我以多种方式修改了我的原始代码。首先,我切换到对数据表使用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 );
        }
    }
}

另外,另一种解决方案是使用类似于读取CSV文件并将其发布到数据库中的框架。它确实有一个用于发布到OleDb源的OleDb存储数据链接。查看示例以了解最终如何将OleDbStorage替换为SqlServerStorage。

听起来您需要将许多.mdb和.csv合并到一个.mdb中。这个答案是基于这样的假设运行的,即您可以使用SQL Server。如果没有,那么考虑下载SQL Express。 使用SQL Server充当多个数据源和目标数据存储之间的代理。将每个数据源脚本化为SQL Server保留表中的插入项。将所有数据加载到保留表中后,执行最后一次推入目标Access数据存储

考虑以下步骤:

在SQL Server中,为导入的CSV数据创建保留表。 创建表CsvImport CustomerID smallint, 姓varchar40, 生日日期时间

创建一个存储过程,其任务是读取给定的CSV文件路径,并插入到SQL Server表中。 创建PROC ReadFromCSV @CsvFilePath varchar1000 像 大部分 插入CsvImport 从@CsvFilePath-'c:\some.csv' 具有 FIELDTERMINATOR=',',-您自己的特定终止符应位于此处 行终止符='\n' 去

创建一个脚本,为磁盘上的每个.csv文件调用此存储过程。也许一些Excel技巧或文件系统目录管道命令可以帮助您创建这些语句。 exec ReadFromCSV'c:\1.csv

对于每个.mdb数据源,创建一个临时链接服务器。 声明@MdbFilePath varchar1000; 选择@MdbFilePath='C:\MyMdb1.mdb'; EXEC master.dbo.sp_addlinkedserver@server=N'MY_ACCESS\u DB_200;',@srvpproduct=N'ACCESS',@provider=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实例中创建一个链接服务器。这是目标数据存储。将SQL Server中的数据选择到Access中。 EXEC master.dbo.sp_addlinkedserver@server=N'MY\u ACCESS\u TARGET',@srvpproduct=N'ACCESS',@provider=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

听起来您需要将许多.mdb和.csv合并到一个.mdb中。这个答案是基于这样的假设运行的,即您可以使用SQL Server。如果没有,那么考虑下载SQL Express。 使用SQL Server充当多个数据源和目标数据存储之间的代理。将每个数据源脚本化为SQL Server保留表中的插入项。将所有数据加载到保留表中后,执行最后一次推入目标Access数据存储

考虑以下步骤:

在S 在SQL Server中,为导入的CSV数据创建一个保留表。 创建表CsvImport CustomerID smallint, 姓varchar40, 生日日期时间

创建一个存储过程,其任务是读取给定的CSV文件路径,并插入到SQL Server表中。 创建PROC ReadFromCSV @CsvFilePath varchar1000 像 大部分 插入CsvImport 从@CsvFilePath-'c:\some.csv' 具有 FIELDTERMINATOR=',',-您自己的特定终止符应位于此处 行终止符='\n' 去

创建一个脚本,为磁盘上的每个.csv文件调用此存储过程。也许一些Excel技巧或文件系统目录管道命令可以帮助您创建这些语句。 exec ReadFromCSV'c:\1.csv

对于每个.mdb数据源,创建一个临时链接服务器。 声明@MdbFilePath varchar1000; 选择@MdbFilePath='C:\MyMdb1.mdb'; EXEC master.dbo.sp_addlinkedserver@server=N'MY_ACCESS\u DB_200;',@srvpproduct=N'ACCESS',@provider=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实例中创建一个链接服务器。这是目标数据存储。将SQL Server中的数据选择到Access中。 EXEC master.dbo.sp_addlinkedserver@server=N'MY\u ACCESS\u TARGET',@srvpproduct=N'ACCESS',@provider=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

目前,我有一个类似的方法,但工作稍微好一点。这看起来仍然很草率,但它与我得到的解决方案类似。我想找出一些更干净的东西。“史密斯,你为什么认为它很邋遢?”如果不使用外部库,更干净的解决方案会是什么样子?任何其他方法都需要遍历列、构建insert语句,然后遍历列和行并执行insert。依我看,这要麻烦得多,需要更多的代码。我已经更新了我的帖子,建议使用文件助手,你可能会觉得更干净。它当然应该使CSV更容易解析。@托马斯-我不知道为什么我认为它草率。我说的似乎有些马虎。我不知道是不是,这就是为什么我要问这个问题。如果我知道一个更干净的解决方案,我就不会要求了。我只是想找到最好的解决办法。现在,就是这样,但感觉可能会更好。然而,我认为我的感觉是错误的。@jsmith-Ok。您可能会再次看到FileHelpers,它被设计用于解析文件并将其推送到其他源中。@Thomas-我计划接受您的答案,但您能稍微更正一下代码吗?这里的一些语法/代码不起作用。我计划自己添加一个答案,这样你就可以看到它是如何工作的。但如果我接受这个答案,我希望未来的人们不必费尽心思去弄清楚我必须做什么,几乎所有的在线网站都出现了一些不起作用的小问题。所以我花了一点时间才弄明白。目前我有一个类似的方法,但工作稍微好一点。这看起来仍然很草率,但它与我得到的解决方案类似。我想找出一些更干净的东西。“史密斯,你为什么认为它很邋遢?”如果不使用外部库,更干净的解决方案会是什么样子?任何其他方法都需要遍历列、构建insert语句,然后遍历列和行并执行insert。依我看,这要麻烦得多,需要更多的代码。我已经更新了我的帖子,建议使用文件助手,你可能会觉得更干净。它当然应该使CSV更容易解析。@托马斯-我不知道为什么我认为它草率。我说的似乎有些马虎。我不知道是不是,这就是为什么我要问这个问题。如果我知道一个更干净的解决方案,我就不会要求了。我只是想找到最好的解决办法。现在,就是这样,但感觉可能会更好。然而,我认为我的感觉是错误的。@jsmith-Ok。您可能会再次看到FileHelpers,它被设计用于解析文件并将其推送到其他源中。@Thomas-我计划接受您的答案,但您能稍微更正一下代码吗?这里的一些语法/代码不起作用。我计划自己添加一个答案,这样你就可以看到它是如何工作的。但如果我接受这个答案,我希望未来的人们不必费尽心思去弄清楚我必须做什么,几乎所有的在线网站都出现了一些不起作用的小问题。所以花了一点时间才弄明白。