web-dev-qa-db-ja.com

EF Code First用にProviderManifestTokenを構成する方法

EFコードファーストを使用するasp.net MVC3プロジェクトがあります。単体テストでは、SQL Server CE 4.0とSQL Server 2008 Expressを使用しています。両方とも、期待どおりにデータベースを生成するEFと完全に連携しました。

ただし、単体テストの外でアプリケーションを実行し、接続文字列を指すと、エラーが発生します

ProviderIncompatibleException:プロバイダーはProviderManifestToken文字列を返しませんでした

これに関するMSのドキュメントを読みましたが、これはEFモデルが生成するSqlVersionトークンのようです。問題は、私がコードファーストアプローチを使用しているため、.edmxファイルも、dbがまだ生成されていないため、メタデータ情報の参照先がわかりません。

接続名を間違った値に変更すると予期されるエラーがスローされるため、データベース名、ユーザー名、およびパスが正しい限り、接続文字列を知っています。どこから始めればよいかわかりません。

ありがとう。

接続文字列は次のとおりです。

<connectionStrings>
  <add
    name="SqlConnection"
    providerName="System.Data.SqlClient"
    connectionString="Data Source=WORKSTATION\SQLEXPRESS;Initial Catalog=CodeFirst;Integrated Security=False;
    Persist Security Info=False;User ID=CodeFirst_user;Password=password1;Connect Timeout=120;MultipleActiveResultSets=True;"/>
</connectionStrings>
41
trevorc

EF 6(リリースされたばかり)を使用している場合は、代替手段があります。

依存関係の解決

新しい 依存関係の解決 機能を使用して、IManifestTokenResolverの実装を登録できます( このプレビュードキュメント as IManifestTokenService)。

この記事 は、DbConfigurationの使用方法についてもう少し情報を提供します。最も簡単な使用方法は次のとおりです。

DbConfigurationType(typeof(EntityFrameworkDbConfiguration))]
public class MyContextContext : DbContext
{
}

この例では、SQL Server接続のメタデータを作成するときにデータベースへのアクセスを回避し、SQL Server 2005の互換性を自動的に指定します。

using System.Data.Common;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.Infrastructure.DependencyResolution;
using System.Data.SqlClient;

/// <summary>
/// A configuration class for SQL Server that specifies SQL 2005 compatability.
/// </summary>
internal sealed class EntityFrameworkDbConfiguration : DbConfiguration
{
    /// <summary>
    /// The provider manifest token to use for SQL Server.
    /// </summary>
    private const string SqlServerManifestToken = @"2005";

    /// <summary>
    /// Initializes a new instance of the <see cref="EntityFrameworkDbConfiguration"/> class.
    /// </summary>
    public EntityFrameworkDbConfiguration()
    {
        this.AddDependencyResolver(new SingletonDependencyResolver<IManifestTokenResolver>(new ManifestTokenService()));
    }

    /// <inheritdoc />
    private sealed class ManifestTokenService : IManifestTokenResolver
    {
        /// <summary>
        /// The default token resolver.
        /// </summary>
        private static readonly IManifestTokenResolver DefaultManifestTokenResolver = new DefaultManifestTokenResolver();

        /// <inheritdoc />
        public string ResolveManifestToken(DbConnection connection)
        {
            if (connection is SqlConnection)
            {
                return SqlServerManifestToken;
            }

            return DefaultManifestTokenResolver.ResolveManifestToken(connection);
        }
    }
}
12
Olly

数時間の検索といじりの後、私はそれを行う方法を見つけました。 DbModelBuilderクラスはDbProviderInfoメソッドでBuildを取るので、EFに依存してOnModelCreatedを呼び出す代わりにそれを使用します。

// 'Entities' is my DbContext subclass, the "container" in EF terms.
public static Entities GetNewContext()
{
    // Get a connection, for example:
    var connection = new SqlConnection(GetConnectionString());

    // Create a DbModelBuilder
    var modelBuilder = new DbModelBuilder();
    // Configure the model builder.
    // I changed my DbContext subclass - added a public version of OnModelCreated and called it ConfigureModelBuilder
    Entities.ConfigureModelBuilder(modelBuilder);

    // Here's where the magic happens.
    // Build the model and pass the ProviderManifestToken (I use 2005 to avoid a bug in precision of sql datetime columns when using concurrency control)
    var model = modelBuilder.Build(new System.Data.Entity.Infrastructure.DbProviderInfo("System.Data.SqlClient", "2005"));
    // Compile the model
    var compiledModel = model.Compile();

    // Create the container (DbContext subclass). Ideally all the previous stuff should be cached.
    return new Entities(connection, compiledModel, true);
}

これには明らかに再編成が必要です(たとえば、コンパイルされたモデルをキャッシュして、コンテキストが作成されるたびに再構築する必要がないようにします)。

私にとって、これは問題を完全に解決しました。楽しい!

10
sinelaw

私の場合、接続文字列名はコンテキストクラス名と一致する必要があります。

接続文字列:

<connectionStrings>
  <add name="NunuContext" connectionString="Data Source=|DataDirectory|Nunu.sdf" providerName="System.Data.SqlServerCe.4.0" />
</connectionStrings>

コンテキストクラス:

using System.Data.Entity;
namespace Nunu.Models
{
    public class NunuContext : DbContext
    {
        System.Data.Entity.DropCreateDatabaseIfModelChanges<Nunu.Models.NunuContext>());

        public DbSet<Nunu.Models.NunuFirst> NunuFirsts { get; set; }

        public DbSet<Nunu.Models.NunuLast> NunuLasts { get; set; }
    }
}
6
asakura89

私はちょうどこの正確な問題を抱えていましたが、SQL Serverサービスが実行されていなかったことが原因です。コンピューターを再起動したばかりで、通常はコンピューターで起動しますが、何らかの理由で起動しませんでした。

6
Bruce Hubbard

データソースをlocalhostconnectionStringに変更すると、問題が解決しました。

1
Bala

Data Source = localhostに変更すると、MS SQL 2008 R2 Expressを使用しても機能しました

1
John

ASP.NETのMVC3チュートリアル で作業しているときに、この問題が発生しました。

私の解決策は最終的に(localhost)名前付きデータソースの代わり。これはローカルの開発作業のために私のボックスでは正常に機能しますが、データベースが別のサーバー上にある場合は役に立ちません。

1
Cameron Combs

「User Id = abcUser; Password = somePwd;」と明示的に指定すると、私の接続文字列では、同じエラーを解決できます。以前、「Trusted_Connection = true;」を使用していたため、Webプロジェクトをデバッグできましたが、エラーが発生し始めました-{「プロバイダーはProviderManifestToken文字列を返しませんでした。」} Webプロジェクトをその下にWebロールとして追加した後、Azureプロジェクトをデバッグしてみました。

同様の状況を経験している人の助けになることを願っています。

ありがとう、Vivek Bahl

1
Vivek Bahl

これは私にとって役立つことが証明されています。

<connectionString="Data Source=WORKSTATION\SQLEXPRESS;Initial Catalog=CodeFirst;User ID=CodeFirst_user;Password=********"/> 
</connectionStrings> 
0
andrew