zoukankan      html  css  js  c++  java
  • SqlBulkCopy 批量复制数据到数据表

    使用 SqlBulkCopy 类只能向 SQL Server 表写入数据。但是,数据源不限于 SQL Server;可以使用任何数据源,只要数据可加载到 DataTable 实例或可使用 IDataReader 实例读取数据

    1. 使用Datatable作为数据源的方式:

    下面的代码使用到了ColumnMappings,因为目标表和数据源Datatable的结构不一致,需要这么一个映射来指定对应关系

      public string SaveJHCData(LzShopBasicData[] datas)
            {
                var result = new AResult();
                SqlConnection con = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["**"].ConnectionString);
                con.Open();
                foreach (var item in datas)
                {
    
                    Logger.Info("数据更新处理,店铺名称:" + item.ShopName + "数据日期" + item.SellDate);
                    try
                    {
                        using (TransactionScope scope = new TransactionScope())
                        {
    
                            DataTable JHCOrderItemsdt = SaveJHCOrderItemsData(item);
                            SqlBulkCopy JHCOrderItemscopy = new SqlBulkCopy(con);
                            JHCOrderItemscopy.ColumnMappings.Add("orderId", "orderId");
                            JHCOrderItemscopy.ColumnMappings.Add("auctionId", "auctionId");
                            JHCOrderItemscopy.ColumnMappings.Add("itemTitle", "itemTitle");
                            JHCOrderItemscopy.ColumnMappings.Add("tradeAmt", "tradeAmt");
                            JHCOrderItemscopy.ColumnMappings.Add("alipayNum", "alipayNum");
                            JHCOrderItemscopy.ColumnMappings.Add("tradeTime", "tradeTime");
                            JHCOrderItemscopy.ColumnMappings.Add("uv", "uv");
                            JHCOrderItemscopy.ColumnMappings.Add("srcId", "srcId");
                            JHCOrderItemscopy.ColumnMappings.Add("srcName", "srcName");
                            JHCOrderItemscopy.ColumnMappings.Add("DataType", "DataType");
                            JHCOrderItemscopy.ColumnMappings.Add("DataDate", "DataDate");
                            JHCOrderItemscopy.ColumnMappings.Add("OrderSourceID", "OrderSourceID");
                            JHCOrderItemscopy.ColumnMappings.Add("ShopName", "ShopName");
                            JHCOrderItemscopy.DestinationTableName = "JHCOrderItems";
                            JHCOrderItemscopy.WriteToServer(JHCOrderItemsdt);
                            result.Updatedata += 1;
                            result.UpdatedataText += item.SellDate + ",";
                            scope.Complete();
                            Logger.Info(item.SellDate + "事务提交");
                        }
                    }
                    catch (Exception ex)
                    {
                        Logger.Error(ex.ToString());
                        continue;
                    }
                }
                con.Close();
                return result.ToSerializeObject();
            }

     2.使用IDataReader作为数据源的方式,这种方式个人认为用的很少,首先目标表和来源表两个数据库连接你都需要拿到,如果两个都可以拿到,一般直接操作sql就可以解决:

    这里是直接拷贝的MSDN的代码,

    用到的AdventureWorks 数据库可以直接在网上下载到,

    using System.Data.SqlClient;
    
    class Program
    {
        static void Main()
        {
            string connectionString = GetConnectionString();
            // Open a sourceConnection to the AdventureWorks database.
            using (SqlConnection sourceConnection =
                       new SqlConnection(connectionString))
            {
                sourceConnection.Open();
    
                // Perform an initial count on the destination table.
                SqlCommand commandRowCount = new SqlCommand(
                    "SELECT COUNT(*) FROM " +
                    "dbo.BulkCopyDemoMatchingColumns;",
                    sourceConnection);
                long countStart = System.Convert.ToInt32(
                    commandRowCount.ExecuteScalar());
                Console.WriteLine("Starting row count = {0}", countStart);
    
                // Get data from the source table as a SqlDataReader.
                SqlCommand commandSourceData = new SqlCommand(
                    "SELECT ProductID, Name, " +
                    "ProductNumber " +
                    "FROM Production.Product;", sourceConnection);
                SqlDataReader reader =
                    commandSourceData.ExecuteReader();
    
                // Open the destination connection. In the real world you would 
                // not use SqlBulkCopy to move data from one table to the other 
                // in the same database. This is for demonstration purposes only.
                using (SqlConnection destinationConnection =
                           new SqlConnection(connectionString))
                {
                    destinationConnection.Open();
    
                    // Set up the bulk copy object. 
                    // Note that the column positions in the source
                    // data reader match the column positions in 
                    // the destination table so there is no need to
                    // map columns.
                    using (SqlBulkCopy bulkCopy =
                               new SqlBulkCopy(destinationConnection))
                    {
                        bulkCopy.DestinationTableName =
                            "dbo.BulkCopyDemoMatchingColumns";
    
                        try
                        {
                            // Write from the source to the destination.
                            bulkCopy.WriteToServer(reader);
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message);
                        }
                        finally
                        {
                            // Close the SqlDataReader. The SqlBulkCopy
                            // object is automatically closed at the end
                            // of the using block.
                            reader.Close();
                        }
                    }
    
                    // Perform a final count on the destination 
                    // table to see how many rows were added.
                    long countEnd = System.Convert.ToInt32(
                        commandRowCount.ExecuteScalar());
                    Console.WriteLine("Ending row count = {0}", countEnd);
                    Console.WriteLine("{0} rows were added.", countEnd - countStart);
                    Console.WriteLine("Press Enter to finish.");
                    Console.ReadLine();
                }
            }
        }
    
        private static string GetConnectionString()
            // To avoid storing the sourceConnection string in your code, 
            // you can retrieve it from a configuration file. 
        {
            return "Data Source=(local); " +
                " Integrated Security=true;" +
                "Initial Catalog=AdventureWorks;";
        }
    }
    View Code

    实战:借助类型反射动态构建Datatable数据源,通过SqlBulkCopy批量保存入库

    1.获取一张空的Datatable

    var dt = bisdal.From<TopBrand>(TopBrand._.ID == -1, OrderByClip.Default).ToDataTable();

    2.填充DataTable,这里是通过遍历外部的集合,把属性属性逐一赋值填充到目标Datatable

             foreach (var item in brandselldataitems)
                        {
                            try
                            {
    
                                TopBrand topbrand = new TopBrand
                                {
                                    BrandIndex = item.mk,
                                    BrandName = item.c58,
                                    Date = date,
                                    WinnerAmt = item.c60,
                                    WinnerPeople = item.c62,
                                    WinnerProNum = item.c61,
                                    HotTaobaoCategoryID = cid
                                };
                                CreateDtByItem<TopBrand>(topbrand, dt);
                            }
                            catch (Exception ex)
                            {
                                Logger.Error(ex.ToString());
                                continue;
                            }
                        }

     这里借助反射,遍历实体属性集合,动态构建DataTableRow对象

           private void CreateDtByItem<T>(T item, DataTable dt)
            {
                System.Reflection.PropertyInfo[] properties = item.GetType().GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
                var newrow = dt.NewRow();
                foreach (System.Reflection.PropertyInfo pitem in properties)
                {
    
                    string name = pitem.Name;
                    if (name == "children")
                    {
                        continue;
                    }
                    object value = pitem.GetValue(item, null);
                    newrow[name] = value == null ? DBNull.Value : value;
                }
                dt.Rows.Add(newrow);
            }

    3.保存入库,

         BulkWriteToServer(con, "TopBrand", dt);

     这里因为目标表和数据源的Datatable数据结构一致,所以省去了ColumnMappings列映射的操作,可以直接WriteToServer保存

         private void BulkWriteToServer(SqlConnection con, string destinationtablename, DataTable sourcedt)
            {
                try
                {
                    if (con.State == ConnectionState.Closed)
                    {
                        con.Open();
                    }
                    SqlBulkCopy topbranddtcopy = new SqlBulkCopy(con);
                    topbranddtcopy.DestinationTableName = destinationtablename;
                    topbranddtcopy.WriteToServer(sourcedt);
                    con.Close();
                }
                catch (Exception ex)
                {
                    Logger.Error("批量新增数据:" + destinationtablename + "," + ex.ToString());
                }
            }

    完整调用代码:

     private void CreateTopBrandData(int date, int cid, List<BrandSellDataItem> brandselldataitems)
            {
                try
                {
                    var dt = bisdal.From<TopBrand>(TopBrand._.ID == -1, OrderByClip.Default).ToDataTable();
                    foreach (var item in brandselldataitems)
                    {
                        try
                        {
    
                            TopBrand topbrand = new TopBrand
                            {
                                BrandIndex = item.mk,
                                BrandName = item.c58,
                                Date = date,
                                WinnerAmt = item.c60,
                                WinnerPeople = item.c62,
                                WinnerProNum = item.c61,
                                HotTaobaoCategoryID = cid
                            };
                            CreateDtByItem<TopBrand>(topbrand, dt);
                        }
                        catch (Exception ex)
                        {
                            Logger.Error(ex.ToString());
                            continue;
                        }
                    }
                    BulkWriteToServer(con, "TopBrand", dt);
                }
                catch (Exception ex)
                {
                    throw new Exception("CreateTopBrandData:" + ex.ToString());
                }
            }
  • 相关阅读:
    axios基本用法
    Iframe父子窗口之间的跨域事件调用和传值
    js 比较两个日期的大小
    小程序webview实践
    小程序入口构造工具&二维码测试工具
    小程序无限层级路由方案
    TypeScript基础类型,类实例和函数类型声明
    小程序多业务线融合【完整分包业务接入】
    浅谈React16框架
    CSS Modules 与 scoped 的不一样
  • 原文地址:https://www.cnblogs.com/LittleFeiHu/p/4050391.html
Copyright © 2011-2022 走看看