如何为EF Code First配置ProviderManifestToken

时间:2011-01-19 22:23:22

标签: entity-framework connection-string code-first

我有一个使用EF代码优先的asp.net MVC3项目。对于我的单元测试,我一直在使用SQL Server CE 4.0和SQL Server 2008 Express。两者都与EF一起完美地生成了我的数据库。

但是,当我在单元测试之外运行我的应用程序并将其指向我的连接字符串时,我收到错误

  

ProviderIncompatibleException:提供程序未返回ProviderManifestToken字符串

我已经阅读了MS文档,看起来这是EF模型生成的SqlVersion标记。问题是我使用代码第一种方法,因此我没有.edmx文件,也不知道在哪里指向我的元数据信息,因为尚未生成数据库。

我知道我的连接字符串,因为db name,username和pass是正确的,因为将它们更改为错误的值会引发预期的错误。不知道从哪里开始。

感谢。

这是我的连接字符串:

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

9 个答案:

答案 0 :(得分:12)

如果您正在使用EF 6(刚刚发布),您可以选择其他方式。

依赖性解决方案

您可以使用新的dependency resolution功能注册IManifestTokenResolver的实施(在this preview documentation中描述为IManifestTokenService)。

This article提供了有关如何使用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);
        }
    }
}

答案 1 :(得分:10)

经过几个小时的搜索和摆弄,我找到了办法。事实上,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);
}

显然,这需要进行一些重组(例如,缓存已编译的模型,这样每次创建上下文时都不需要重新构建它。)

对我来说,这完全解决了这个问题。享受!

答案 2 :(得分:6)

我刚才遇到了这个确切的问题,但我追溯到我的SQL Server服务没有运行。我刚刚重新启动了我的计算机,通常它是自己开始的,但不是出于某种原因。

答案 3 :(得分:6)

就我而言,我的连接字符串名称必须与上下文类名称匹配。

连接字符串:

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

答案 4 :(得分:1)

我在处理MVC3 tutorial on ASP.NET时遇到了这个问题。

我的解决方案最终是使用(localhost)而不是命名数据源。对于本地开发工作,这在我的盒子上工作正常,但如果数据库在单独的服务器上则无济于事。

答案 5 :(得分:1)

更改为数据源= localhost 也使用MS SQL 2008 R2 Express为我工作

答案 6 :(得分:1)

将数据源更改为localhost中的connectionString解决了我的问题。

答案 7 :(得分:0)

这对我有用:

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

答案 8 :(得分:0)

我在上面看到了一些有关oracle的评论,因此以下是针对oracle调整的“ EntityFrameworkDbConfiguration”代码:

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