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

BKS*_*eon 1 c# connection-string heroku npgsql entity-framework-6

一个棘手的(令人沮丧的问题) - 也许你们大家可能很聪明地解决它:

问题

我希望能够使用Entity Frameworks读取/写入我的数据库.我有一个在Heroku(简单的脚手架)上运行的简单app rails.我想连接到这个数据库并操纵记录.好消息是我可以使用npgsql成功连接到该数据库.坏消息是我不能用实体框架来做.这是我收到的错误:

System.Data.Entity.Core.ProviderIncompatibleException:从数据库获取提供程序信息时发生错误.这可能是由实体框架使用不正确的连接字符串引起的.检查内部异常以获取详细信息,并确保连接字符串正确.---> System.Data.Entity.Core.ProviderIncompatibleException:提供程序未返回ProviderManifestToken字符串.---> System.IO.FileLoadException:无法加载文件或程序集'Npgsql,Version = 3.1.2.0,Culture = neutral,PublicKeyToken = 5d8b90d52f46fda7'或其依赖项之一.定位的程序集的清单定义与程序集引用不匹配.(HRESULT异常:0x80131040)

这是堆栈跟踪:

   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
Run Code Online (Sandbox Code Playgroud)

这是我的连接字符串:

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;
Run Code Online (Sandbox Code Playgroud)

这是我用来连接和读取数据库(来自播放器表)的"Hello world".它成功打印:"Lionel Messi"在控制台上.大!

            #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
Run Code Online (Sandbox Code Playgroud)

问题是当我尝试使用实体框架时.它大大地失败了,带来了一个痛苦的错误.我正在使用完全相同的连接字符串,并且不能为我的生活找出我出错的地方.也许你可以轻松发现问题?

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);
            }           
        }
Run Code Online (Sandbox Code Playgroud)

这是我的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>
Run Code Online (Sandbox Code Playgroud)

当我直接传入一个连接字符串 - 同一个工作得很好以便先检索记录时,我得到了一个奇怪的例外:

"关键字不支持'用户名'" - 显然是指传入的连接字符串.

using (var db = new PlayerContext(sqlBuilder.ToString()))
                { // etc }
Run Code Online (Sandbox Code Playgroud)

还奇怪的是,我在编译前收到警告:

"警告1发现无法解析的相同从属程序集的不同版本之间存在冲突.当日志详细程度设置为详细时,这些引用冲突将在构建日志中列出.pg-EF-test2"也许这与Npgsql有关?

任何援助将不胜感激.

Lam*_*ser 9

看起来当前版本中的"EntityFramework6.Npgsql"nuget包具有错误定义的依赖项.它将"Npgsql(> = 3.1.0)"列为依赖项,但它实际上需要3.1.2或更高版本中的Npgsql.

因此修复很简单 - 只需将Npgsql包更新到最新版本即可."Update-Package Npgsql"应该可以解决问题.

至于带有字符串参数的上下文构造函数 - 您有一个奇怪的异常,因为该构造函数希望您从配置文件中传递连接字符串的名称.你应该像这样使用它:

using (var db = new PlayerContext("PlayerContext"))
{ }
Run Code Online (Sandbox Code Playgroud)