简体   繁体   English

实体框架6-Npgsql-连接字符串错误

[英]Entity Framework 6 - Npgsql - connection string error

A tricky (and frustrating problem) - perhaps you folks may be clever enough to solve it: 一个棘手的问题(令人沮丧的问题)-也许您可能很聪明地解决了这个问题:

Problem 问题

I want to be able to read/write to my database using Entity Frameworks. 我希望能够使用实体框架读取/写入我的数据库。 I have got a simple app rails running on Heroku (straightforward scaffold). 我在Heroku(简单的脚手架)上运行了一个简单的应用程序导轨。 I want to connect to this database and manipulate records. 我想连接到该数据库并处理记录。 The good news is that I can successfully connect to that database using npgsql. 好消息是我可以使用npgsql成功连接到该数据库。 The bad news is that I cannot do it with Entity Frameworks. 坏消息是我不能使用实体框架来做到这一点。 This is the error I'm receiving: 这是我收到的错误:

System.Data.Entity.Core.ProviderIncompatibleException: An error occurred while getting provider information from the database. System.Data.Entity.Core.ProviderIncompatibleException:从数据库获取提供程序信息时发生错误。 This can be caused by Entity Framework using an incorrect connection string. 这可能是由于实体框架使用错误的连接字符串引起的。 Check the inner exceptions for details and ensure that the connection string is correct. 检查内部异常以获取详细信息,并确保连接字符串正确。 ---> System.Data.Entity.Core.ProviderIncompatibleException: The provider did not return a ProviderManifestToken string. ---> System.Data.Entity.Core.ProviderIncompatibleException:提供程序未返回ProviderManifestToken字符串。 ---> System.IO.FileLoadException: Could not load file or assembly 'Npgsql, Version=3.1.2.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7' or one of its dependencies. ---> System.IO.FileLoadException:无法加载文件或程序集'Npgsql,Version = 3.1.2.0,Culture = neutral,PublicKeyToken = 5d8b90d52f46fda7'或其依赖项之一。 The located assembly's manifest definition does not match the assembly reference. 找到的程序集的清单定义与程序集引用不匹配。 (Exception from HRESULT: 0x80131040) (来自HRESULT的异常:0x80131040)

Here is the stack trace: 这是堆栈跟踪:

   at Npgsql.NpgsqlServices.GetDbProviderManifestToken(DbConnection connection) 
   at System.Data.Entity.Core.Common.DbProviderServices.GetProviderManifestToken(DbConnection connection) 
   --- End of inner exception stack trace --- 
   at System.Data.Entity.Core.Common.DbProviderServices.GetProviderManifestToken(DbConnection connection) 
   at System.Data.Entity.Utilities.DbProviderServicesExtensions.GetProviderManifestTokenChecked(DbProviderServices providerServices, DbConnection connection) 
   --- End of inner exception stack trace --- 
   at System.Data.Entity.Utilities.DbProviderServicesExtensions.GetProviderManifestTokenChecked(DbProviderServices providerServices, DbConnection connection) 
   at System.Data.Entity.Infrastructure.DefaultManifestTokenResolver.<>c__DisplayClass1.<ResolveManifestToken>b__0(Tuple`3 k) 
   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory) 
   at System.Data.Entity.Infrastructure.DefaultManifestTokenResolver.ResolveManifestToken(DbConnection connection) 
   at System.Data.Entity.Utilities.DbConnectionExtensions.GetProviderInfo(DbConnection connection, DbProviderManifest& providerManifest) 
   at System.Data.Entity.DbModelBuilder.Build(DbConnection providerConnection) 
   at System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext) 
   at System.Data.Entity.Internal.RetryLazy`2.GetValue(TInput input) 
   at System.Data.Entity.Internal.LazyInternalContext.InitializeContext() 
   at System.Data.Entity.Internal.InternalContext.Initialize() 
   at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType) 
   at System.Data.Entity.Internal.Linq.InternalSet`1.Initialize() 
   at System.Data.Entity.Internal.Linq.InternalSet`1.get_InternalContext() 
   at System.Data.Entity.Infrastructure.DbQuery`1.System.Linq.IQueryable.get_Provider() 
   at System.Linq.Queryable.Select[TSource,TResult](IQueryable`1 source, Expression`1 selector) 
   at ge_EntityFrameworkTest.Program.<Test>d__4.MoveNext() in c:\Users\Koshy\Documents\Visual Studio 2013\Projects\Practice\ge-EntityFrameworkTest\ge-EntityFrameworkTest\Program.cs:line 118

Here is my connection string: 这是我的连接字符串:

NpgsqlConnectionStringBuilder sqlBuilder = new NpgsqlConnectionStringBuilder();
                sqlBuilder.Username = user;
                sqlBuilder.Password = password;
                sqlBuilder.Host = host;
                sqlBuilder.Port = Int32.Parse(port);
                sqlBuilder.Database = database;
                sqlBuilder.Pooling = true;
                sqlBuilder.UseSslStream = true;     
                sqlBuilder.SslMode = Npgsql.SslMode.Require;
                sqlBuilder.TrustServerCertificate = true;

Here is my “Hello world” that I am using to connect and read from my database (from the players table). 这是我用来连接并从数据库(从玩家表中读取)的“ Hello world”。 It is successfully printing: “Lionel Messi” on to the console. 它已成功打印:“ Lionel Messi”到控制台。 Great! 大!

            #region connectingAndReadingDatabase
            using (var conn = new NpgsqlConnection(sqlBuilder.ToString()))
            {
                conn.Open();
                using (var cmd = new NpgsqlCommand())
                {
                    cmd.Connection = conn;

                    // Retrieve all rows
                    cmd.CommandText = "SELECT * FROM players";
                    using (var reader = cmd.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                            Console.WriteLine(reader.GetString(1));
                        }
                    }
                }
            }
            #endregion

The problem is when I try to use Entity Frameworks. 问题是当我尝试使用实体框架时。 It fails massively with a painful error. 它因严重的错误而大量失败。 I am using exactly the same connection string, and cannot for the life of me work out where I'm going wrong. 我使用的连接字符串完全相同,并且无法终生确定我要去哪里。 Perhaps you may be able to easily spot the problem? 也许您可以轻松发现问题?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Net.Http;
using Newtonsoft.Json;
using Npgsql;
using System.Data.Entity;
using System.Data.Common;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
using System.Configuration;
using System.Data.Entity.ModelConfiguration.Conventions;


// Here is the code pertaining to my hello world entity framework example:

        [Table("players", Schema = "public")]
        public  class Player
        {
            [Key]
            [Column("id")]
            public int id { get; set; }
             [Column("name")]
            public string Name { get; set; }
             [Column("team")]
            public string Team { get; set; }
            public Player() { }
        }

        class NpgsqlConfiguration : System.Data.Entity.DbConfiguration
        {
            public NpgsqlConfiguration()
            {
                SetProviderServices ("Npgsql", Npgsql.NpgsqlServices.Instance);
                SetProviderFactory ("Npgsql", Npgsql.NpgsqlFactory.Instance);
                SetDefaultConnectionFactory (new Npgsql.NpgsqlConnectionFactory ());
            }
        }

        [DbConfigurationType(typeof(NpgsqlConfiguration))]
        public class PlayerContext : DbContext
        {     
            public PlayerContext(DbConnection connection): base(connection, true)
            {                
            }

            public DbSet<Player> Players { get; set; }
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {

                modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
                //modelBuilder.Conventions.Add<CascadeDeleteAttributeConvention>();
                modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
                modelBuilder.HasDefaultSchema("public");
                base.OnModelCreating(modelBuilder);
            }           
        }

And here is my app.config file 这是我的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>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
  </startup>  
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="v12.0" />
      </parameters>
    </defaultConnectionFactory>
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
      <provider invariantName="Npgsql" type="Npgsql.NpgsqlServices, EntityFramework6.Npgsql" />
    </providers>    
  </entityFramework>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Npgsql" publicKeyToken="5d8b90d52f46fda7" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
  <system.data>
    <DbProviderFactories>
      <add name="Npgsql Data Provider"
            invariant="Npgsql"
            description="Data Provider for PostgreSQL"
            type="Npgsql.NpgsqlFactory, Npgsql" />
    </DbProviderFactories>
  </system.data>
  <connectionStrings>
    <add name="PlayerContext" connectionString="Username=hjanadgkizjmgf;Password=password;Host=ec2-54-235-250-156.compute-1.amazonaws.com;Port=5432;Database=deek4ap6cf2a1;Pooling=true;Use SSL Stream=True;SSL Mode=Require;TrustServerCertificate=True;" providerName="Npgsql" />
  </connectionStrings>
</configuration>

When I pass in a connection string directly - the same one which worked so well to retrieve records earlier, I get this curious exception: 当我直接传递一个连接字符串时-可以很好地及早检索记录的同一个字符串,我得到了一个奇怪的异常:

“Keyword not supported 'username'” – obviously referring to the connection string passed in. “关键字不支持'用户名'” –显然是指传入的连接字符串。

using (var db = new PlayerContext(sqlBuilder.ToString()))
                { // etc }

Also curiously, I receive a warning before compiling: 同样奇怪的是,我在编译之前收到警告:

“Warning 1 Found conflicts between different versions of the same dependent assembly that could not be resolved. “警告1发现了无法解决的相同从属程序集的不同版本之间的冲突。 These reference conflicts are listed in the build log when log verbosity is set to detailed. 将日志详细程度设置为“详细”时,这些参考冲突会在构建日志中列出。 pg-EF-test2” perhaps it's something to do with Npgsql? pg-EF-test2”,也许与Npgsql有关?

Any assistance would be much appreciated. 任何帮助将不胜感激。

Looks like the "EntityFramework6.Npgsql" nuget package in the current version has incorrectly defined dependencies. 看起来当前版本中的“ EntityFramework6.Npgsql” nuget程序包具有错误定义的依赖项。 It lists "Npgsql (>= 3.1.0)" as a dependency but it actually requires Npgsql in version 3.1.2 or higher. 它列出了“ Npgsql(> = 3.1.0)”作为依赖项,但实际上它需要版本3.1.2或更高版本的Npgsql。

So the fix is simple - just update the Npgsql package to the latest version. 因此修复很简单-只需将Npgsql软件包更新为最新版本即可。 "Update-Package Npgsql" should do the trick. “ Update-Package Npgsql”应该可以解决问题。

And as for the context constructor with a string parameter - you got a weird exception because that constructor expects you to pass the name of the connection string from your config file. 对于带有字符串参数的上下文构造函数,您会收到一个奇怪的异常,因为该构造函数希望您从配置文件中传递连接字符串的名称 You should use it like this: 您应该这样使用它:

using (var db = new PlayerContext("PlayerContext"))
{ }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM