C# 如何处理实体框架内部创建的SQLITE命令?

C# 如何处理实体框架内部创建的SQLITE命令?,c#,entity-framework,sqlite,C#,Entity Framework,Sqlite,我在System.Data.SQLite v1.0.94.0写入SQLite错误5时遇到问题:打开新连接时,数据库被锁定到日志。这似乎是由于EntityFrameworkV6.0没有处理所有SQLITE命令造成的 我首先使用实体框架的代码,因此无法使用 一种场景是使用IQueryable,其中SQLiteCommand未被释放 IQueryable<TEntity> query = context.Set<TEntity>(); var result = query.To

我在System.Data.SQLite v1.0.94.0写入SQLite错误5时遇到问题:打开新连接时,数据库被锁定到日志。这似乎是由于EntityFrameworkV6.0没有处理所有SQLITE命令造成的

我首先使用实体框架的代码,因此无法使用

一种场景是使用IQueryable,其中SQLiteCommand未被释放

IQueryable<TEntity> query = context.Set<TEntity>();
var result = query.ToList();
如何跟踪这些未经处理的命令,以便手动处理它们


我希望避免呼叫GC.Collect

这一讨论似乎表明,定义互操作遗留设置是一种解决方法,而不是返回到一个可以工作的旧版本

这种情况的根本原因是实体框架间接创建了 SQLiteCommand对象,然后无法处理它。 此外,它似乎没有公开这些内部创建的命令,也没有显式地处理它们的方法,因此外部调用程序无法清理这些命令。这似乎很奇怪,因为几乎所有的IDbCommand实现都可能需要某种本地资源。此外,即使是.NET Framework本身提供的DbCommand基类也实现了IDisposable,即用作SQLiteCommand基类的类。

是的,SQLite.NET.Settings.targets文件中的InteropLegacyClose MSBuild属性需要设置为true,并且定义INTEROP_LEGACY_CLOSE=1;需要添加到正在使用的Visual Studio版本的SQLite.INTEROP.20XX.[vs]props文件中的INTEROP_EXTRA_DEFINES属性中。

更新:dotConnect for SQLLite看起来是一个免费的专业版,但不是免费的。。。也许值得一看


更新2:如果这是EF的一个bug,那么即使针对SQL Server,使用它的每个人都会有问题卡那沃氏松柏

一点也不,似乎只有在1.0.8xxx左右的SQLLite用户报告了该错误,他们在该版本中更改了dispose方法。。。EF提供程序可以不同,例如,您可以将其设置为SQLLite bug reported或SQLServer bug not reported等,如下所示

<system.data>
  <DbProviderFactories>
    <add name="SQLite Data Provider"
          invariant="System.Data.SQLite"
          description="Data Provider for SQLite"
          type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" />
  </DbProviderFactories>
</system.data>


Oliver Wickenden在该帖中发布了一个有效的解决方法:

他说:只需调用ClearQliteCommandConnectionHelper即可;在应用程序加载开始时。然后,这将保留一个活动命令列表,并在它们指向已关闭的连接时将其连接设置为Null


这对我来说很有用。

DbContext实现IDisposable只需将其放在using语句中即可。我已经在处理DbContext,但我会检查是否有两个上下文同时打开。@PaulZahra讨论的论坛线程不再存在。我不知道当命令和读取器发生在实体内部时,如何立即处理它们Framework@BenRobinson看起来,即使DBContext可以被正确地处理,问题仍然存在,似乎有内部对象保持连接的活动状态。如果这是EF的一个bug,那么即使是针对SQL Server,使用它的每个人都会有问题。真的吗?SQLite是一个软件库,它实现了一个自包含、无服务器、零配置、事务性SQL数据库引擎。SQLite是世界上部署最广泛的SQL数据库引擎。让我怀疑使用EF和SQL Server的人是否会受到影响。@PaulZahra在EF版本保持不变的情况下,出现在特定提供程序中的一个错误定义为特定提供程序的错误。我没有说你不能改变供应商,相反,我说如果这是一个EF问题,它也会出现在其他供应商。无法关闭连接将在SQL Server连接中显示为不断增加的连接,但在SQLite中显示为锁定的数据库。SQLite.NET提供程序有一个bug,而不是EF@PanagiotisKanavos如果有人为汽车制造扳手的人制造了改进的新扳手并停止制造旧扳手。。。必须更换的是扳手制造商,而不是汽车?这是有争议的,让我们就此罢休吧。。。如果有一个泛型类处理所有事情,如果每个提供者都有专门的“dispose”,那么情况就不是这样了。。。您似乎忽略了一个事实,即许多SQLLite/EF用户报告此错误,而没有SQL Server/EF用户报告此错误。
<providers> 
  <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" /> 
</providers>
public static class ClearSQLiteCommandConnectionHelper
{
    private static readonly List<SQLiteCommand> OpenCommands = new List<SQLiteCommand>();

    public static void Initialise()
    {
        SQLiteConnection.Changed += SqLiteConnectionOnChanged;
    }

    private static void SqLiteConnectionOnChanged(object sender, ConnectionEventArgs connectionEventArgs)
    {
        if (connectionEventArgs.EventType == SQLiteConnectionEventType.NewCommand && connectionEventArgs.Command is SQLiteCommand)
        {
            OpenCommands.Add((SQLiteCommand)connectionEventArgs.Command);
        }
        else if (connectionEventArgs.EventType == SQLiteConnectionEventType.DisposingCommand && connectionEventArgs.Command is SQLiteCommand)
        {
            OpenCommands.Remove((SQLiteCommand)connectionEventArgs.Command);
        }

        if (connectionEventArgs.EventType == SQLiteConnectionEventType.Closed)
        {
            var commands = OpenCommands.ToList();
            foreach (var cmd in commands)
            {
                if (cmd.Connection == null)
                {
                    OpenCommands.Remove(cmd);
                }
                else if (cmd.Connection.State == ConnectionState.Closed)
                {
                    cmd.Connection = null;
                    OpenCommands.Remove(cmd);
                }
            }
        }
    }
}