没有 App.config 的 SQLite 实体框架

Posted

技术标签:

【中文标题】没有 App.config 的 SQLite 实体框架【英文标题】:SQLite Entity Framework without App.config 【发布时间】:2015-11-26 00:00:51 【问题描述】:

对于 3d 方应用程序插件,必须使用 SQLite 实体框架数据库优先方法。我搜索了所有互联网,包括Add a DbProviderFactory without an App.Config、Problems using Entity Framework 6 and SQLite 和许多其他。我尝试以不同的方式和组合使用它们,但没有任何帮助:

"一个未处理的异常类型 在 mscorlib.dll 中发生“System.Data.Entity.Core.MetadataException”。 附加信息:指定的架构无效。错误: AutosuggestModel.ssdl (2,2):错误 0152:没有实体框架提供程序 为具有不变名称的 ADO.NET 提供程序找到 'System.Data.SQLite.EF6'。确保提供程序已在 应用程序配置文件的“entityFramework”部分。”

解决方案中有一个测试控制台应用程序。使用这个最小的 App.config 它可以工作:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>
  <entityFramework>
    <providers>
      <provider invariantName="System.Data.SQLite.EF6" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
    </providers>
  </entityFramework>
  <system.data>
    <DbProviderFactories>
      <add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".NET Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" />
    </DbProviderFactories>
  </system.data>
</configuration>

连接字符串已经在代码中实现。使用的包是:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="EntityFramework" version="6.1.3" targetFramework="net452" />
  <package id="System.Data.SQLite" version="1.0.98.1" targetFramework="net452" />
  <package id="System.Data.SQLite.Core" version="1.0.98.1" targetFramework="net452" />
  <package id="System.Data.SQLite.EF6" version="1.0.98.1" targetFramework="net452" />
  <package id="System.Data.SQLite.Linq" version="1.0.98.1" targetFramework="net452" />
</packages>

请提供所有必需的代码并指定插入位置。提前致谢。

【问题讨论】:

sqlite 和 EF 的问题是:数据库初始化程序无法正常工作,因为包中不支持创建数据库和创建表(至少我使用的版本)。您的代码确实看起来很奇怪。首先定义不变的 System.Data.SQLite.EF6,然后不再使用它。您的问题与提供商无关,而是与代码有关。尝试将 DbProviderFactories 中的不变量重命名为“System.Data.SQLite.EF6”,但这里可能还缺少其他错误。 谢谢,但是有了这样的 App.config 一切正常,我已经有了数据库。我需要应用程序在没有 App.сconfig 的情况下运行。借助上面链接的答案,可以删除“system.data”部分,但其他部分仍然需要。 啊,你是这个意思。好吧,您需要 app.config,因为您让 DbContext 知道 EF 必须使用此连接类型。你的 DbContext 的构造函数有一个重载,它实际上需要一个 SqlConnection,我认为它可能会起作用,调用如下:base(new SQLiteConnection([connection string]),true) 再次感谢,但是“连接字符串已经在代码中实现了”。 【参考方案1】:

这是一个示例代码,说明了如何实现目标。

namespace SqliteEFNoConfig

    using System.Configuration;
    using System.Data;
    using System.Data.Common;
    using System.Data.Entity;
    using System.Data.Entity.Core.Common;
    using System.Data.SQLite;
    using System.Data.SQLite.EF6;
    using System.Linq;

    internal class Program
    
        private static void Main()
        
            // EF manages the connection via the DbContext instantiation
            // connection string is set in config
            // Use this code if you want to use a config file
            // with only the connection string
            //using (var model = new Model1())
            //
            //    var dbSetProperty = model.dbSetProperty.ToList();
            //

            // Alternative method: 
            // Use this code if you don't want to use a config file
            // You will also need to use the override constructor shown below,
            // in your EF Model class
            var connectionString = @"data source = PathToSqliteDB";
            using (var connection = new SQLiteConnection(connectionString))
            
                using (var model = new Model1(connection))
                
                    var dbSetProperty = model.dbSetProperty.ToList();
                
            
        
    

    class SqliteDbConfiguration : DbConfiguration
    
        public SqliteDbConfiguration()
        
            string assemblyName = typeof (SQLiteProviderFactory).Assembly.GetName().Name;

            RegisterDbProviderFactories(assemblyName );
            SetProviderFactory(assemblyName, SQLiteFactory.Instance);
            SetProviderFactory(assemblyName, SQLiteProviderFactory.Instance);
            SetProviderServices(assemblyName,
                (DbProviderServices) SQLiteProviderFactory.Instance.GetService(
                    typeof (DbProviderServices)));
        

        static void RegisterDbProviderFactories(string assemblyName)
        
            var dataSet = ConfigurationManager.GetSection("system.data") as DataSet;
            if (dataSet != null)
            
                var dbProviderFactoriesDataTable = dataSet.Tables.OfType<DataTable>()
                    .First(x => x.TableName == typeof (DbProviderFactories).Name);

                var dataRow = dbProviderFactoriesDataTable.Rows.OfType<DataRow>()
                    .FirstOrDefault(x => x.ItemArray[2].ToString() == assemblyName);

                if (dataRow != null)
                    dbProviderFactoriesDataTable.Rows.Remove(dataRow);

                dbProviderFactoriesDataTable.Rows.Add(
                    "SQLite Data Provider (Entity Framework 6)",
                    ".NET Framework Data Provider for SQLite (Entity Framework 6)",
                    assemblyName,
                    typeof (SQLiteProviderFactory).AssemblyQualifiedName
                    );
            
        
    

如果您决定在配置文件中添加连接字符串,那么您需要在 EF 模型中添加以下构造函数。

public Model1(DbConnection connection)
    : base(connection, true)


注意:上面的代码只是一个关于如何实现目标的示例,您必须根据自己的需要进行调整。假设您使用的是 EF Code First 方法,则提供上述代码。

【讨论】:

它不能开箱即用。您需要将其调整为您的代码。为此,我专门添加了“通知”部分。 我调整了。但它不起作用。自己试试。目标是 - 控制台应用程序必须在 删除 App.config 文件后工作。 它有效。我刚刚又检查了一遍。您确实意识到 Main 中的第一个示例代码需要配置文件,但其中只需要连接字符串。而“替代方法”根本不需要任何配置文件。这就是我所说的“您需要根据自己的需要进行调整”。 您写道“它有效。我刚刚又检查了一遍。”请上传您的示例并提供链接。我在问题中特别要求给出一个完整的工作示例。 只使用替代方法。从 Main 中删除任何其他代码。不用说,您还需要将 'PathToSqliteDB' 替换为 sqlite db 的路径。仅供参考,我在控制台应用程序中使用完全相同的示例,但没有配置文件。这就是为什么我知道它有效。

以上是关于没有 App.config 的 SQLite 实体框架的主要内容,如果未能解决你的问题,请参考以下文章

实体类----app-config

c# - 在运行时更改 App.Config 后,实体框架 ConnectionString 不会更新

Postgresql 和实体框架

如何从 DBContext(实体框架核心)中的 App.config(不是 .net 核心应用程序)读取值

使用实体框架 app.config 如何在 Dev、Stage 和 Production 环境之间切换

Flask:程序结构