我提出的问题需要一些介绍。我有一个应用程序,每5分钟从一个文件夹导入小文件和电子邮件到自己的SQL Server数据库。
非常重要现在第1部分并不是什么大问题。然而,第2部分引起了一些担忧。如果在成功导入后无法删除该文件(例如由于缺少访问权限),则下次我的应用程序查看该文件夹时,将一次又一次地导入该文件,直到某人修复了访问权限问题。
因此,我想知道以下方法是否可以安全地工作,而不会丢失数据:
这就是我到达问题标题的地方:如果之前的步骤没有引发异常,那么最后一次提交步骤是否会成功?我可以安全地在提交之前删除文件,没有丢失文件的风险?如果SQL Server在事务期间关闭怎么办?或者,如果文件删除失败,我是否应该从数据库中删除记录?
答案 0 :(得分:1)
您所说的“交易”仅用于确保数据完全提交到数据库。要添加持久性以确保不能多次导入文件,您有多个选项,但我们考虑以下内容:
INSERT
失败,从而回滚整个“事务”。这当然只有在文件名实际上是唯一的时才有效。如果文件名不唯一,那么看看你是否能找到足够的信息。通常情况下,您可以添加其他域信息(例如发票#,客户#等)以使其唯一,因此INSERT
仍然失败。您需要意识到的一件事是,您正在管理两种不同的技术。删除文件,或者我应该说你的尝试,与数据库事务没有任何关系,除非你制作它。所以,假设你有这样的流程:
using (SqlConnection c ...)
using (SqlCommand cmd ...)
{
SqlTransaction t = c.BeginTransaction();
try
{
// update database
// try to delete file
t.Commit();
}
catch (Exception ex)
{
// you know something failed
// you can catch more specific exceptions and respond here
}
}
如果未达到t.Commit()
,则数据库将不会更新。
答案 1 :(得分:0)
通常我会先将文件存档到另一个位置。然后我会建立一个存储导入元数据的地方,这将存储文件名和文件的日期以及导入的成功或失败。然后你可以证明每个文件都已导入,并且仍然有任何失败的副本。
然后我会在事务中运行该进程以导入文件。我会在启动导入事务之前将有关该文件的元数据放入数据库中(因此它赢了;在失败时回滚)然后在提交之后,我会向元数据添加信息以让我知道文件已经成功进口。当然作为数据人,我会在SSIS中完成所有这些工作,我可以使用本机日志记录来帮助我记录每个步骤(有助于查看故障发生的位置)。导入完成后,我会从处理位置删除该文件,但我会在存档位置保留一段时间。 (后来有一些alawys问题,为什么数据看起来很像它有助于手头有实际文件向他们展示他们以这种方式发送给你的信息!)
答案 2 :(得分:0)
假设您使用的是相对较新版本的Windows(Vista +)且正在使用NTFS,您可以在事务中登记文件操作。
我不相信.NET库内置了这个内容,但是有一个第三方库here可以让你做这样的事情:
// Wrap a file copy and a database insert in the same transaction
TxFileManager fileMgr = new TxFileManager();
using (TransactionScope scope1 = new TransactionScope())
{
// Delete the file
fileMgr.DeleteFile(fileName);
// Do some database stuff
dbMgr.ExecuteNonQuery(insertSql);
scope1.Complete();
}