草庐IT

c# - SQLite 即使在连接关闭后仍保持数据库锁定

coder 2023-07-09 原文

我在 ASP.NET 应用程序(框架 4.0)中使用 System.Data.SQLite 提供程序。 我遇到的问题是,当我在 SQLite 数据库的表中插入某些内容时,数据库被锁定并且即使在处理连接后也不会释放锁定。

尝试访问文件时,错误是:“进程无法访问文件 'catalog.sqlite',因为它正被另一个进程使用。”

我的代码非常简单,我打开连接,从 SQLServer 数据库中读取一些数据,将该数据插入 SQLite(通过 SQLiteDataAdapter),然后关闭连接并处理所有内容以确保安全。但是,当我在用数据填充文件后尝试压缩文件时,仍然会遇到该错误。

我在 StackOverflow 上阅读了各种建议,但没有一个有助于解决问题(关闭防病毒软件、更改事务模型、等待几秒钟然后压缩文件、将所有插入调用包装到交易等。但都没有帮助解决这个问题。

也许有一些特定于 ASP.NET 的东西(多线程是问题?即使我在一台开发机器上测试它,那里只有一个对该函数的调用并且没有并发?)

作为旁注,我尝试避免使用 DataTable 和 SQLiteDataAdapter 并直接仅使用 SQLiteCommand,这样就很有魅力了。当然,我可以继续将查询构建为字符串,而不是使用数据适配器,但是当构建了一个框架来执行此操作时,我觉得有点尴尬。

最佳答案

我在使用 System.Data.Sqlite.dll 版本 1.0.82.0 附带的设计器生成的数据集/表适配器时遇到了同样的问题——关闭连接后我们无法读取数据库使用 System.IO.FileStream 的文件。我正确地处理了连接和表适配器,并且没有使用连接池。

根据我的第一次搜索(例如 thisthis thread ),库本身似乎存在问题——对象未正确释放和/或池问题(我不使用)。

阅读您的问题后,我尝试仅使用 SQLiteCommand 对象来复制问题,但我发现当您不处理它们时就会出现问题。 更新 2012-11-27 19:37 UTC:this ticket 进一步证实了这一点对于 System.Data.SQLite,开发人员在其中解释说“所有与连接关联的 SQLiteCommand 和 SQLiteDataReader 对象 [应该] 正确处理”。

然后我重新打开生成的 TableAdapter,我看到没有执行 Dispose 方法——所以实际上创建的命令没有被释放。我实现了它,负责处理所有命令,我没有遇到任何问题。

这是 C# 中的代码,希望对您有所帮助。请注意,代码是从 original in Visual Basic 转换而来的,因此预计会出现一些转换错误。

//In Table Adapter    
protected override void Dispose(bool disposing)
{
   base.Dispose(disposing);

    Common.DisposeTableAdapter(disposing, _adapter, _commandCollection);
}

public static class Common
{
    /// <summary>
    /// Disposes a TableAdapter generated by SQLite Designer
    /// </summary>
    /// <param name="disposing"></param>
    /// <param name="adapter"></param>
    /// <param name="commandCollection"></param>
    /// <remarks>You must dispose all the command,
    /// otherwise the file remains locked and cannot be accessed
    /// (for example, for reading or deletion)</remarks>
    public static void DisposeTableAdapter(
        bool disposing,
        System.Data.SQLite.SQLiteDataAdapter adapter,
        IEnumerable<System.Data.SQLite.SQLiteCommand> commandCollection)
    {
        if (disposing) {
            DisposeSQLiteTableAdapter(adapter);

            foreach (object currentCommand_loopVariable in commandCollection)
            {
                currentCommand = currentCommand_loopVariable;
                currentCommand.Dispose();
            }
        }
    }

    public static void DisposeSQLiteTableAdapter(
            System.Data.SQLite.SQLiteDataAdapter adapter)
    {
        if (adapter != null) {
            DisposeSQLiteTableAdapterCommands(adapter);

            adapter.Dispose();
        }
    }

    public static void DisposeSQLiteTableAdapterCommands(
            System.Data.SQLite.SQLiteDataAdapter adapter)
    {
        foreach (object currentCommand_loopVariable in {
            adapter.UpdateCommand,
            adapter.InsertCommand,
            adapter.DeleteCommand,
            adapter.SelectCommand})
        {
            currentCommand = currentCommand_loopVariable;
            if (currentCommand != null) {
                currentCommand.Dispose();
            }
        }
    }
}

更新 2013-07-05 17:36 UTC gorogm's answer强调两件重要的事情:

  • 根据 changelog在 System.Data.SQLite 的官方网站上,从版本 1.0.84.0 开始,应该不需要上面的代码,因为库会处理这个。我没有测试过这个,但在最坏的情况下你只需要这个片段:

    //In Table Adapter    
    protected override void Dispose(bool disposing)
    {
      base.Dispose(disposing);
    
      this.Adapter.Dispose();
    }
    
  • 关于 TableAdapterDispose 调用的实现:最好把它放在分部类中,这样数据集重新生成就不会影响此代码(以及您可能需要添加的任何其他代码)。

关于c# - SQLite 即使在连接关闭后仍保持数据库锁定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12532729/

有关c# - SQLite 即使在连接关闭后仍保持数据库锁定的更多相关文章

  1. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  2. ruby - 续集在添加关联时访问many_to_many连接表 - 2

    我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以

  3. ruby - 无法在 60 秒内获得稳定的 Firefox 连接 (127.0.0.1 :7055) - 2

    我使用的是Firefox版本36.0.1和Selenium-Webdrivergem版本2.45.0。我能够创建Firefox实例,但无法使用脚本继续进行进一步的操作无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055)错误。有人能帮帮我吗? 最佳答案 我遇到了同样的问题。降级到firefoxv33后一切正常。您可以找到旧版本here 关于ruby-无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055),我们在StackOverflow上找到一个类

  4. ruby - 即使失败也继续进行多主机测试 - 2

    我已经构建了一些serverspec代码来在多个主机上运行一组测试。问题是当任何测试失败时,测试会在当前主机停止。即使测试失败,我也希望它继续在所有主机上运行。Rakefile:namespace:specdotask:all=>hosts.map{|h|'spec:'+h.split('.')[0]}hosts.eachdo|host|begindesc"Runserverspecto#{host}"RSpec::Core::RakeTask.new(host)do|t|ENV['TARGET_HOST']=hostt.pattern="spec/cfengine3/*_spec.r

  5. ruby - Ruby 有 `Pair` 数据类型吗? - 2

    有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

  6. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  7. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  8. ruby - 如何关闭 ruby​​ gem "Spreadsheet?"中的文件 - 2

    下面的代码在我第一次运行它时就可以正常工作:require'rubygems'require'spreadsheet'book=Spreadsheet.open'/Users/me/myruby/Mywks.xls'sheet=book.worksheet0row=sheet.row(1)putsrow[1]book.write'/Users/me/myruby/Mywks.xls'当我再次运行它时,我会收到更多消息,例如:/Library/Ruby/Gems/1.8/gems/spreadsheet-0.6.5.9/lib/spreadsheet/excel/reader.rb:11

  9. ruby - 我如何添加二进制数据来遏制 POST - 2

    我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_

  10. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

随机推荐