在sql server compact edition上执行Insert OR Update(upsert)

时间:2009-04-08 03:05:48

标签: c# sql entity-framework sql-server-ce upsert

我有c#项目正在使用sqlserver压缩版和实体框架进行数据访问。我需要向db插入或更新大量5000+或更多的行,因此如果密钥存在,则更新记录(如果不插入)。我无法找到一种方法来实现这一点与紧凑版和EF具有可怕的性能,即在核心i7计算机上花费2分钟。我已经尝试搜索记录,看它是否存在,然后插入,如果没有,或更新,如果它,搜索是杀手。我已经尝试编译搜索查询,但只做了一点改进。我尝试的另一件事是在try catch中插入记录,如果更新失败,但这迫使我在每条记录上保存更改以获得异常,而不是在最后是性能杀手。显然我不能使用存储过程,因为它是紧凑版。另外我看过只是在db上直接执行t-sql,但是在compact中缺少进程语句似乎排除了这一点。 我在全世界范围内搜寻和思考。我真的想使用紧凑型,如果我可以过度表达部署的好处和能力,以防止用户挖掘数据库。任何建议都将不胜感激。

由于

7 个答案:

答案 0 :(得分:6)

当我们使用SQL CE(和SQL 2005 Express)时,我们总是首先调用更新,然后在udate给出行数为0时调用插入。这很容易实现,并且不需要exnsice try..catch blocks for control flow。

答案 1 :(得分:2)

鉴于你的问题陈述,我猜这个软件假设一个相对强大的环境。您是否考虑过确定sqlce并自行完成的任务?从本质上讲,从相关表中获取所有ID(键?)的排序列表,并在排队插入之前检查该列表中的每个对象键?

这使得一些假设对于典型的数据库来说是个坏消息,但是你可以在sqlce中逃脱。例如,它假定在您执行此插入时,不会由其他用户插入或显着修改行。

如果密钥列表太长而无法合理地保留在内存中以进行此类检查,我恐怕我会说sqlce可能不适合这项工作。 :(

答案 2 :(得分:2)

也许您可以通过使用简单查询获得您所寻求的结果。 假设要插入或更新的表格是这样的

TABLE original
     id integer,
     value char(100)

首先你可以使用新值创建一个临时表(你可以使用SELECT INTO或其他方法来创建它)

TABLE temp
    id integer,
    value char(100)

现在,您需要做两件事,更新原始行,然后插入新值

UPDATE original 
SET original.value = temp.value
FROM original, temp
WHERE original.id = temp.id

INSERT INTO original 
SELECT * from temp 
WHERE temp.id not IN (select o.id from original o)

答案 3 :(得分:2)

我不确定这是否可行,因为我没有使用实体框架,但您是否尝试先运行更新并检查rowcount - 如果没有更新行,则插入?这可能比捕获异常更快。对控制流使用异常通常是一种不好的做法,并且通常会使事情急剧减慢。

如果您可以直接编写SQL,那么最快的方法是将所有数据放入临时表中,然后更新存在的内容并插入休止符(如上面的Andrea Bertani的例子)。通过在插入中的select中的原始表上使用左连接,并且排除原始表中非空的值的任何行,您应该获得稍微好一点的结果:

INSERT INTO original
SELECT * FROM temp
LEFT JOIN original ON original.id = temp.id
WHERE original.id IS NULL

答案 4 :(得分:2)

我建议直接使用SqlCeResultSet。你失去了EF的良好类型安全性,但性能令人难以置信的快。我们从ADO.NET 2.0风格的TypeDataSets切换到SqlCeResultSet和SqlCeDataReader,速度提高了20到50倍。

答案 5 :(得分:1)

请参阅SqlCeResultSet。对于.NETCF项目,我删除了几乎所有的sql代码,而不是这个类。 只需在这里搜索“SqlCeResultSet”和msdn。

快速概述:

  1. 打开resultSet。 如果您需要搜索(存在检查),则必须提供结果集的索引。

  2. 寻找结果集&阅读以检查是否找到了该行。即使在具有数万行的表中,这也非常快(因为搜索使用了索引)。

  3. 插入或更新记录(请参阅SqlCeResultSet.NewRecord)。


  4. 我们已经成功开发了一个带有sqlce数据库的项目,该数据库的主产品表超过65000行(带有4个索引的读/写)。

答案 6 :(得分:0)

SQL Server紧凑版在此时尚处于早期开发阶段。此外,根据您的设备,内存磁盘访问速度可能非常慢,并且SQLCE加上.NET类型安全开销非常密集。它适用于非常静态的数据存储。

我建议你使用更轻量级的API或考虑SQLite。