How to configure ProviderManifestToken for EF Code First
Asked Answered
A

10

42

I have a asp.net MVC3 project using EF code-first. For my unit testing I have been using SQL Server CE 4.0 and SQL Server 2008 Express. Both have worked perfectly with EF generating my database as expected.

However, when I run my application outside of a unit test and point it at my connection strings I get the error

ProviderIncompatibleException: The provider did not return a ProviderManifestToken string

I have read the MS documentation on this and it appears this is a SqlVersion token that the EF model generates. The problem is that I am using the code first approach so I have no .edmx file nor do I know where to point my metadata info to because the db hasn't been generated yet.

I know my connection strings as far as db name, username, and pass are correct because changing them to wrong values throws the expected error. Not sure where to begin.

Thanks.

Here is my connection string:

<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>
Antonia answered 19/1, 2011 at 22:23 Comment(3)
Are you sure the connection string is used? It should have same name as your class derived from DbContext.Sept
It is. I found what the problem is. It was a couple of things. (1)The db should not be pre-created in SqlServer even if it is empty. Let EF do this. (2)An initial catalog name should be included if it is not declared in the DbContext. (3)I could not create the db under Medium Trust. Hope this helps someone.Antonia
@nameEquals... how did you solve item 3 above?Lundin
G
13

If you're using EF 6 (just released) you have an alternative.

Dependency Resolution

You can use the new dependency resolution feature to register an implementation of IManifestTokenResolver (described in this preview documentation as IManifestTokenService).

This article gives a bit more information on how to use DbConfiguration. The easiest way to use it is like this:

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

This example avoids any trip to the database when building the metadata for SQL Server connections, and automatically specifies SQL Server 2005 compatability.

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);
        }
    }
}
Goldshell answered 22/10, 2013 at 0:13 Comment(2)
Is anything like this necessary for using EF with ODP.NET without actually connecting to the database?Cyme
@ObliviousSage I've never used EF with Oracle, but from this article it looks as though you do need to do something like this. The article's author found that "11g" was the appropriate token value in his case.Goldshell
S
10

After hours of searching & fiddling, I found a way to do it. Turns out the DbModelBuilder class takes a DbProviderInfo in its Build method, so I use that instead of relying on EF to call 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);
}

Obviously this needs some reorganization (e.g. cache the compiled model so you don't need to re-build it every time a context is created).

For me this completely solved the problem. Enjoy!

Saratov answered 21/8, 2012 at 18:3 Comment(3)
Nice- someone finally answered the question from the title of the post!!Runthrough
For those working with apps that must attach to multiple SQL instances, I have confirmed this solution works when connecting to multiple SQL versions (2005 and 2008).Catercousin
Nice - I wish I saw this before! Have a look at how you can do this a bit more easily in EF 6 - see my answer below.Goldshell
A
6

I just had this exact problem but I traced it down to my SQL Server service wasn't running. I had just restarted my computer and usually it starts on it's own but didn't for some reason.

Argillaceous answered 10/5, 2011 at 14:12 Comment(2)
Same here. I just checked my Sql Server Configuration Manager and the Sql Server service wasn't running for some reason. Once I started the service it worked perfectlyWasher
Same thing for me, but my SQLEXPRESS service was not running. It did not work with normal SQL Server which was running.Archil
F
6

In my case, my connection string name must match the context class name.

Connection String:

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

Context Class:

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; }
    }
}
Franciskus answered 27/4, 2012 at 22:24 Comment(0)
L
1

I had this problem when working through the MVC3 tutorial on ASP.NET.

My solution ended up being to use (localhost) instead of a named Data Source. This works fine on my box, for local dev work, but wouldn't help if the database were on a separate server.

Latoshalatouche answered 9/3, 2011 at 17:37 Comment(0)
Q
1

I found, when i provided explicit "User Id=abcUser; Password=somePwd;" in my connection string i am able to resolve the same error. Earlier i was using the "Trusted_Connection=true;", which allowed me to debug my web project, but started giving me error - {"The provider did not return a ProviderManifestToken string."} as soon as i added the Windows azure project and tried debugging the Azure project after adding my web project as a web role under it.

Hope it helps some one experiencing a similar situation.

Thanks, Vivek Bahl

Quacksalver answered 7/11, 2011 at 6:12 Comment(0)
D
1

Changing to Data Source=localhost worked for me also using MS SQL 2008 R2 Express

Diazole answered 26/12, 2011 at 5:16 Comment(0)
F
1

Changing the Data Source to localhost in the connectionString solved my problem.

Filiation answered 17/5, 2012 at 19:21 Comment(0)
I
0

I see some comments about oracle above, so here's the code for "EntityFrameworkDbConfiguration" adjusted for oracle:

internal sealed class EntityFrameworkDbConfiguration : DbConfiguration
{
    /// <summary>
    /// Initializes a new instance of the <see cref="EntityFrameworkDbConfiguration"/> class.
    /// </summary>
    public EntityFrameworkDbConfiguration()
    {
        this.AddDependencyResolver(Oracle.ManagedDataAccess.EntityFramework.EFOracleProviderServices.Instance);
    }
}
Ianteen answered 28/8, 2020 at 11:29 Comment(0)
S
-2

This has proven helpful for me:

<connectionString="Data Source=WORKSTATION\SQLEXPRESS;Initial Catalog=CodeFirst;User ID=CodeFirst_user;Password=********"/> 
</connectionStrings> 
Staphylococcus answered 1/3, 2012 at 1:35 Comment(1)
What in your connection string has proven helpful? I don't see what's unique about it.Trough

© 2022 - 2024 — McMap. All rights reserved.