42 votes

Comment configurer ProviderManifestToken pour EF Code First

J'ai un asp.net MVC3 projet à l'aide d'EF code-première. Pour mes tests unitaires j'ai été à l'aide de SQL Server CE 4.0 et SQL Server 2008 Express. Tous deux ont travaillé parfaitement avec les objectifs EF génération de ma base de données comme prévu.

Cependant, lorsque je lance mon application en dehors d'une unité de test et de le montrer à mes chaînes de connexion, je reçois l'erreur

ProviderIncompatibleException: Le fournisseur n'a pas retourné un ProviderManifestToken chaîne

J'ai lu le MS documentation sur ce sujet et il semble que c'est un SqlVersion jeton que le modèle EF génère. Le problème est que je suis en utilisant la première approche de code donc je n'ai pas d' .edmx le fichier de je ne sais où, de mon point de métadonnées info parce que la bd n'a pas été généré encore.

Je sais que mon chaînes de connexion aussi loin que db, nom d'utilisateur, et passe sont corrects parce que les modifier à mal les valeurs jette l'erreur attendue. Vous ne savez pas où commencer.

Merci.

Voici ma chaîne de connexion:

<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>

13voto

Olly Points 2982

Si vous utilisez EF 6 (vient de sortir), vous disposez d'une alternative.

De La Résolution Des Dépendances

Vous pouvez utiliser la nouvelle de la résolution des dépendances fonctionnalité pour enregistrer une mise en œuvre de l' IManifestTokenResolver (décrit dans cet aperçu de la documentation en tant que IManifestTokenService).

Cet article donne un peu plus d'informations sur la façon d'utiliser DbConfiguration. La façon la plus simple d'utilisation, il est comme ceci:

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

Cet exemple permet d'éviter tout voyage dans la base de données lors de la construction de métadonnées pour les connexions SQL Server, et indique automatiquement SQL Server 2005 sur la compatibilité.

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);
        }
    }
}

10voto

sinelaw Points 6641

Après des heures de recherches et de tripes, j'ai trouvé un moyen de le faire. Il s'avère que la classe DbModelBuilder prend un DbProviderInfo dans sa méthode Build , je l'utilise donc au lieu de compter sur EF pour appeler 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);
}
 

Évidemment, cela nécessite une réorganisation (par exemple, mettre en cache le modèle compilé pour qu'il ne soit pas nécessaire de le reconstruire chaque fois qu'un contexte est créé).

Pour moi, cela a complètement résolu le problème. Prendre plaisir!

6voto

Bruce Hubbard Points 177

Je viens d'avoir ce problème exact, mais je l'ai retracé jusqu'à mon service SQL Server n'était pas en cours d'exécution. Je venais juste de redémarrer mon ordinateur et il démarre généralement tout seul, mais ne l'a pas fait pour une raison quelconque.

6voto

asakura89 Points 161

Dans mon cas, le nom de ma chaîne de connexion doit correspondre au nom de la classe de contexte.

Chaîne de connexion:

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

Classe de contexte:

 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; }
    }
}
 

1voto

Cameron Combs Points 38

J'ai eu ce problème lorsque vous avez suivi le didacticiel MVC3 sur ASP.NET .

Ma solution a finalement été d'utiliser (localhost) au lieu d'une source de données nommée. Cela fonctionne bien sur ma boîte, pour le travail de développement local, mais ne serait d'aucun secours si la base de données était sur un serveur séparé.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X