Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/276.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在sql server compact edition上执行插入或更新(upsert)_C#_Sql_Entity Framework_Sql Server Ce_Upsert - Fatal编程技术网

C# 在sql server compact edition上执行插入或更新(upsert)

C# 在sql server compact edition上执行插入或更新(upsert),c#,sql,entity-framework,sql-server-ce,upsert,C#,Sql,Entity Framework,Sql Server Ce,Upsert,我有一个c项目,它使用SQLServerCompactEdition和EntityFramework进行数据访问。我需要插入或更新大量的行,5000+或更多的行到数据库中,因此如果键存在,则更新记录(如果不插入)。我找不到一种方法来做到这一点,紧凑版和EF没有可怕的性能,即需要2分钟以上的核心i7电脑。我试着搜索记录,看看它是否存在,然后插入,如果不存在或更新,如果有,搜索是杀手。我尝试过编译搜索查询,但只得到了一点小小的改进。我尝试过的另一件事是在try-catch中插入记录,如果更新失败,则

我有一个c项目,它使用SQLServerCompactEdition和EntityFramework进行数据访问。我需要插入或更新大量的行,5000+或更多的行到数据库中,因此如果键存在,则更新记录(如果不插入)。我找不到一种方法来做到这一点,紧凑版和EF没有可怕的性能,即需要2分钟以上的核心i7电脑。我试着搜索记录,看看它是否存在,然后插入,如果不存在或更新,如果有,搜索是杀手。我尝试过编译搜索查询,但只得到了一点小小的改进。我尝试过的另一件事是在try-catch中插入记录,如果更新失败,则会强制我保存每个记录上的更改以获得异常,而不是在最后,这是一个性能杀手。显然,我不能使用存储过程,因为它是压缩版。我还研究了直接在db上执行t-sql,但是在compact中缺少过程语句似乎排除了这一点。 我已经找遍了全世界,找遍了各种各样的点子。我真的很想使用compact,如果我可以过度表达部署的好处和防止用户在数据库中挖掘的能力。如有任何建议,将不胜感激


谢谢

给出了您的问题陈述,我猜这个软件假设了一个相对坚固的环境。您是否考虑过将确定sqlce的任务交给您自己来完成?从本质上说,抓取所有idskey的排序列表?从相关表中,并在将其排队等待插入之前,根据该列表检查每个对象键

这使得一些假设对于一个典型的DB来说是个坏消息,但是在sqlce中,您可能会侥幸逃脱。例如,它假设在您执行此插入时,其他用户不会插入或显著修改行


如果密钥列表太长,无法合理地保存在内存中进行此类检查,恐怕我会说sqlce可能不是适合此工作的工具

也许你可以通过简单的查询得到你想要的结果。 假设要插入或更新的表如下所示

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)

我不确定这是否可行,因为我没有使用实体框架,但您是否尝试过先运行更新并检查行数-如果没有更新行,则插入?这可能比捕获异常更快。在控制流中使用异常通常是一种不好的做法,并且通常会显著降低速度

如果可以直接编写SQL,那么最快的方法就是将所有数据放入一个临时表中,然后更新现有数据并插入其余数据,如上面Andrea Bertani的示例所示。通过在插入中的select中对原始表使用左联接,并从原始表中排除任何值不为null的行,应该可以获得更好的结果:

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

我建议直接使用SqlCeResultSet。您失去了EF的良好类型安全性,但性能却非常快。我们从ADO.NET 2.0风格的TypeDataSet切换到SqlCeResultSet和SqlCeDataReader,速度提高了20到50倍。

SQL Server compact edition在这一点上处于开发初期。此外,根据您的设备,内存磁盘访问可能非常慢,SQLCE plus.NET类型的安全开销非常大。它最适合于一个相当静态的数据存储


我建议您使用更轻的API或考虑SQLite。< /P> < P>参见SQLCURESULTSSET。对于一个.NETCF项目,为了支持这个类,我删除了几乎所有的sql代码。 只需在此处搜索SqlCeResultSet和msdn

快速概述:

打开结果集。 如果需要查找存在性检查,则必须为结果集提供索引

查找结果集并读取以检查是否找到该行。因为seek使用索引,所以即使在具有上万行的表上,速度也非常快

插入或更新记录请参见SqlCeResultSet.NewRecord


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

在使用SQL CE和SQL 2005 Express时,如果udate给出的行数为0,我们总是先调用更新,然后调用插入。这是一个非常简单的实现方法,并且不需要花费太多的费用。请尝试控制流的catch块。

谢谢您的建议。明天我将花一些时间测试这些想法的性能。今天,我尝试了各种方法来使用sql express及其闪电般的速度,甚至不使用存储过程。使用其存储过程和新的me
rge声明几乎是即时的。谢谢,这确实提供了一些很好的改进,但仍然低于我需要的性能。对于Compact Edition来说,我的数据需求太多了。当CE不支持if时,如果行数为0,如何进行插入?@Sahuagin-我们单独调用更新SQL,并使用.NET中ExecuteOnQuery的结果来决定是否需要调用插入。