Как настроить ProviderManifestToken для EF Code First
У меня есть проект asp.net MVC3 с использованием EF-кода. Для моего модульного тестирования я использую SQL Server CE 4.0 и SQL Server 2008 Express. Оба отлично работали с EF, генерируя мою базу данных, как ожидалось.
Однако, когда я запускаю приложение за пределами unit test и указываю его на строки подключения, я получаю сообщение об ошибке
ProviderIncompatibleException: поставщик не вернул строку ProviderManifestToken
Я прочитал документацию MS по этому вопросу, и, похоже, это токен SqlVersion
, который генерирует EF-модель. Проблема в том, что я использую первый подход кода, поэтому у меня нет файла .edmx
, и я не знаю, где указать информацию о метаданных, потому что db еще не создан.
Я знаю, что строки подключения до имени 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>
Ответы
Ответ 1
После нескольких часов поиска и вождения я нашел способ сделать это. Оказывается, класс 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 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
Если вы используете 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);
}
}
}
Ответ 3
У меня просто была эта точная проблема, но я проследил ее до того, что моя служба SQL Server не была запущена. Я только что перезапустил свой компьютер, и обычно он начинается сам по себе, но не по какой-то причине.
Ответ 4
В моем случае имя строки подключения должно соответствовать имени класса контекста.
Строка подключения:
<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; }
}
}
Ответ 5
У меня была эта проблема при работе с учебником MVC3 по ASP.NET.
Моим решением оказалось использование (localhost)
вместо имени источника данных. Это отлично работает на моем ящике, для локальной работы с разработчиками, но не помогло бы, если бы база данных находилась на отдельном сервере.
Ответ 6
Я обнаружил, когда я указал явный "User Id = abcUser; Password = somePwd;" в моей строке подключения я могу решить ту же ошибку. Раньше я использовал "Trusted_Connection = true;", что позволило мне отладить мой веб-проект, но начал давать мне ошибку - { "Поставщик не вернул строку ProviderManifestToken." }, Как только я добавил проект azure Windows и попыталась отладить проект Azure после добавления моего веб-проекта в качестве веб-роли под ним.
Надеюсь, что это поможет кому-то испытать подобную ситуацию.
Спасибо,
Vivek Bahl
Ответ 7
Переход на Источник данных = localhost работал у меня также с использованием MS SQL 2008 R2 Express
Ответ 8
Изменение источника данных на localhost
в connectionString
решило мою проблему.
Ответ 9
Это оказалось полезным для меня:
<connectionString="Data Source=WORKSTATION\SQLEXPRESS;Initial Catalog=CodeFirst;User ID=CodeFirst_user;Password=********"/>
</connectionStrings>