数据库
首页 > 数据库> > C#-带有实体框架的SqlBulkCopy(和更新)

C#-带有实体框架的SqlBulkCopy(和更新)

作者:互联网

最近我到达了一个点,实体框架不再满足我将数据从一个数据库复制到另一个数据库的需求(它实在太慢了,我想提取比以往更多的数据).因此,我开始研究替代方法,并找到了SqlBulkCopy方法.问题是SqlBulkCopy不允许我“ UPSERT”.再次,开始寻找解决方案,并遇到了DataTable.Merge(table)函数.

根据我的研究,似乎“最佳实践”是使用SqlBulkCopy将我的数据导入“临时表”,然后使用DataTable.Merge(),然后以某种方式保存更改.保存更改是我遇到问题的部分.我有以下代码:

static void Main(string[] args)
    {
        using(var mdb = new meldbContext())
        using(var odb = new ocmgccazTestEnvDbContext())
        {
            /*Is there a better way to clear the staging table that
              doesn't require me to write actual SQL?*/
            odb.Database.ExecuteSqlCommand("DELETE FROM almCallDetail_staging");

            var lastUpdateTime = (from p in odb.almCallDetail
                                  select p.time_of_contact).Max();

            var query = from p in mdb.cl_contact_event
                        where p.time_of_contact >= lastUpdateTime
                        select new almCallDetail
                        {
                            id = p.id,
                            contact_list_name = p.contact_list_name,
                            account_number = p.account_number,
                            time_of_contact = p.time_of_contact
                        };

            var conn = new SqlConnection(odb.Database.Connection.ConnectionString);
            var bulkCopy = new SqlBulkCopy(conn)
            {
                BatchSize = 5000,
                DestinationTableName = "almCallDetail_staging"
            };

            conn.Open();
                bulkCopy.WriteToServer(query.ToDataTable());    

                var originalTable = (from p in odb.almCallDetail
                                     where p.time_of_contact >= lastUpdateTime
                                     select p).ToDataTable();

                var stagingTable = (from p in odb.almCallDetail_staging
                                    select p).ToDataTable();

                /*Merge happens but the data is not actually saved to the almCallDetail
                  Table (originalTable)...*/
                originalTable.Merge(stagingTable);
            conn.Close();
        }
    }

如何更改此设置以保存合并操作的结果?

有没有更好的方法可以编码此代码,以实现快速导入/更新大量数据的目标?

进一步说明:我基本上只是从生产服务器的表中复制数据,以便(以后)创建各种数据集,然后可以将其转换为该组的报告.我有一个计划任务,它将每30分钟左右运行一次此代码,以使数据保持相对最新,并且我希望整个过程尽可能高效.即从生产服务器中提取所需的最少数据量,并将其复制到我的本地数据库中.

我当前的实现完全基于实体框架.它:

>从生产服务器中获取当天的数据集
>遍历该组数据
>将其与本地数据库进行比较
>根据需要更新/添加

它完全可以满足我的需求,但是速度非常慢(出于多种原因,我都知道这些原因).因此,我希望对其进行更新.

解决方法:

这里最快的方法(如果不使用SSIS)可能是使用带有MERGE语句的存储过程.
在您的存储过程中添加链接的服务器.这样的事情应该起作用:

exec sp_addlinkedserver @server = 'ProductionServer'

MERGE [LocalServer].dbName.dbo.TableName AS Target
USING (SELECT * FROM [ProductionServer].dbName.dbo.TableName) AS source
ON TARGET.Id = source.Id
WHEN MATCHED
THEN UPDATE 
SET Field1 = source.Field1, Field2 = source.Field2, ---etc....
WHEN NOT MATCHED BY TARGET THEN
INSERT (Field1, Field2, Field3) 
VALUES (Field1, Field2, Field3) ;

另外,如果您需要从其中一个表中删除所有内容,则可以使用TRUNCATE进行此操作,这比Delete from快得多.像这样:

TRUNCATE TABLE TableName;

标签:ado-net,linq,c,entity-framework
来源: https://codeday.me/bug/20191031/1977268.html