web-dev-qa-db-fra.com

Comment configurer ProviderManifestToken pour EF Code First

J'ai un projet asp.net MVC3 utilisant le code EF en premier. Pour mes tests unitaires, j'utilisais SQL Server CE 4.0 et SQL Server 2008 Express. Les deux ont parfaitement fonctionné avec EF générant ma base de données comme prévu.

Cependant, lorsque j'exécute mon application en dehors d'un test unitaire et que je la pointe sur mes chaînes de connexion, l'erreur s'affiche 

ProviderIncompatibleException: le fournisseur n'a pas renvoyé de chaîne ProviderManifestToken

J'ai lu la documentation de MS à ce sujet et il apparaît qu'il s'agit d'un jeton SqlVersion généré par le modèle EF. Le problème est que j'utilise l'approche de code d'abord, je n'ai donc aucun fichier .edmx et je ne sais pas non plus où indiquer mes informations de métadonnées car la base de données n'a pas encore été générée.

Je sais que mes chaînes de connexion en ce qui concerne le nom de la base de données, le nom d'utilisateur et le mot de passe sont correctes, car les remplacer par des valeurs incorrectes génère 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>
41
trevorc

Si vous utilisez EF 6 (récemment publié), vous avez une alternative.

Résolution de dépendance

Vous pouvez utiliser la nouvelle fonctionnalité dependency resolution pour enregistrer une implémentation de IManifestTokenResolver (décrite dans cet aperçu documentation en tant que IManifestTokenService). 

Cet article donne un peu plus d'informations sur l'utilisation de DbConfiguration. La façon la plus simple de l'utiliser est la suivante:

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

Cet exemple évite les déplacements dans la base de données lors de la création des métadonnées pour les connexions SQL Server et spécifie automatiquement la compatibilité de 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

Après des heures de recherche et de violon, j'ai trouvé un moyen de le faire. Il se trouve que la classe DbModelBuilder prend une DbProviderInfo dans sa méthode Build; je l'utilise donc au lieu de m'appuyer 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);
}

Il est évident que 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!

10
sinelaw

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

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 de manière autonome, mais ne l'a pas fait pour une raison quelconque.

6
Bruce Hubbard

Changer la source de données en localhost dans connectionString a résolu mon problème. 

1
Bala

Passer à Data Source = localhost a également travaillé pour moi avec MS SQL 2008 R2 Express

1
John

J'ai eu ce problème lorsque vous travaillez dans 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é 

1
Cameron Combs

J'ai trouvé, quand j'ai fourni explicite "User Id = abcUser; Password = somePwd;" dans ma chaîne de connexion je suis capable de résoudre la même erreur. Auparavant, j'utilisais "Trusted_Connection = true;", ce qui m'a permis de déboguer mon projet Web, mais a commencé à me donner une erreur - {"Le fournisseur n'a pas renvoyé de chaîne ProviderManifestToken."} Dès que j'ai ajouté le projet Windows Azure J'ai essayé de déboguer le projet Azure après avoir ajouté mon projet Web en tant que rôle Web. 

J'espère que cela aidera quelqu'un qui vit une situation similaire.

Merci, Vivek Bahl

1
Vivek Bahl

Cela s’est avéré utile pour moi:

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