Недопустимое значение ключа 'attachdbfilename' в WebSecurity.InitializeDatabaseConnection

Я получаю это сообщение об ошибке при попытке инициализировать подключение к базе данных с помощью SimpleMembership. Первый оператор инициализации проходит, а второй нет. Цель состоит в том, чтобы использовать строки подключения, определенные в конфигурации службы Azure, при запуске эмулятора Azure или при развертывании.

Web.config:

<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=aspnet-**********;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnet-**********.mdf" providerName="System.Data.SqlClient" />
</connectionStrings>

Файлы конфигурации Azure .cscfg:

<Setting name="SqlConnectionString" value="Server=Data Source=(LocalDb)\v11.0;Initial Catalog=aspnet-********;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnet-********.mdf" />

SimpleMembershipInitializer:

string connectionStringName = "DefaultConnection";
string connectionString = CloudConfigurationManager.GetSetting("SqlConnectionString");
const string userTableName = "UserProfile";
const string providerName = "System.Data.SqlClient";
const string userIdColumn = "UserId";
const string userNameColumn = "UserName";

// This works fine.
// WebSecurity.InitializeDatabaseConnection(connectionStringName, userTableName, userIdColumn, userNameColumn, autoCreateTables: true);

// This throws exception.
// WebSecurity.InitializeDatabaseConnection(connectionString, providerName, userTableName, userIdColumn, userNameColumn, autoCreateTables: true);

Среда: Visual Studio 2012, EntityFramework 5.0 и MVC4 RTM со структурой SimpleMembership по умолчанию.

Полная трассировка стека:

[ArgumentException: Invalid value for key 'attachdbfilename'.]
   System.Data.SqlClient.SqlConnectionString.VerifyLocalHostAndFixup(String& host, Boolean enforceLocalHost, Boolean fixup) +888986
   System.Data.SqlClient.SqlConnectionString..ctor(String connectionString) +5330002
   System.Data.SqlClient.SqlConnectionFactory.CreateConnectionOptions(String connectionString, DbConnectionOptions previous) +24
   System.Data.ProviderBase.DbConnectionFactory.GetConnectionPoolGroup(DbConnectionPoolKey key, DbConnectionPoolGroupOptions poolOptions, DbConnectionOptions& userConnectionOptions) +167
   System.Data.SqlClient.SqlConnection.ConnectionString_Set(DbConnectionPoolKey key) +61
   System.Data.SqlClient.SqlConnection.set_ConnectionString(String value) +66
   WebMatrix.Data.DbProviderFactoryWrapper.CreateConnection(String connectionString) +96
   WebMatrix.Data.<>c__DisplayClass15.<OpenConnectionStringInternal>b__14() +16
   WebMatrix.Data.Database.get_Connection() +19
   WebMatrix.Data.Database.EnsureConnectionOpen() +12
   WebMatrix.Data.<QueryInternal>d__0.MoveNext() +66
   System.Linq.Enumerable.FirstOrDefault(IEnumerable`1 source) +164
   WebMatrix.Data.Database.QuerySingle(String commandText, Object[] args) +103
   WebMatrix.WebData.DatabaseWrapper.QuerySingle(String commandText, Object[] parameters) +14
   WebMatrix.WebData.SimpleMembershipProvider.CheckTableExists(IDatabase db, String tableName) +57
   WebMatrix.WebData.SimpleMembershipProvider.CreateTablesIfNeeded() +49
   WebMatrix.WebData.WebSecurity.InitializeMembershipProvider(SimpleMembershipProvider simpleMembership, DatabaseConnectionInfo connect, String userTableName, String userIdColumn, String userNameColumn, Boolean createTables) +73
   WebMatrix.WebData.WebSecurity.InitializeProviders(DatabaseConnectionInfo connect, String userTableName, String userIdColumn, String userNameColumn, Boolean autoCreateTables) +51
   WebMatrix.WebData.WebSecurity.InitializeDatabaseConnection(String connectionString, String providerName, String userTableName, String userIdColumn, String userNameColumn, Boolean autoCreateTables) +63
   MyProject.Filters.SimpleMembershipInitializer..ctor() in c:\Repos\MyRepo\trunk\Web\MyProject\Filters\InitializeSimpleMembershipAttribute.cs:55

[InvalidOperationException: The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.microsoft.com/fwlink/?LinkId=256588]
   MyProject.Filters.SimpleMembershipInitializer..ctor() in c:\Repos\MyRepo\trunk\Web\MyProject\Filters\InitializeSimpleMembershipAttribute.cs:59

[TargetInvocationException: Exception has been thrown by the target of an invocation.]
   System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) +0
   System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +113
   System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +232
   System.Activator.CreateInstance(Type type, Boolean nonPublic) +83
   System.Activator.CreateInstance(Type type) +6
   System.Threading.LazyHelpers`1.ActivatorFactorySelector() +68
   System.Threading.LazyInitializer.EnsureInitializedCore(T& target, Boolean& initialized, Object& syncLock, Func`1 valueFactory) +115
   System.Threading.LazyInitializer.EnsureInitialized(T& target, Boolean& initialized, Object& syncLock) +106
   MyProject.Filters.InitializeSimpleMembershipAttribute.OnActionExecuting(ActionExecutingContext filterContext) in c:\Repos\MyRepo\trunk\Web\MyProject\Filters\InitializeSimpleMembershipAttribute.cs:23
   System.Web.Mvc.Async.AsyncControllerActionInvoker.InvokeActionMethodFilterAsynchronously(IActionFilter filter, ActionExecutingContext preContext, Func`1 nextInChain) +69
   System.Web.Mvc.Async.<>c__DisplayClass3b.<BeginInvokeActionMethodWithFilters>b__35() +21
   System.Web.Mvc.Async.AsyncControllerActionInvoker.InvokeActionMethodFilterAsynchronously(IActionFilter filter, ActionExecutingContext preContext, Func`1 nextInChain) +489
   System.Web.Mvc.Async.<>c__DisplayClass3b.<BeginInvokeActionMethodWithFilters>b__35() +21
   System.Web.Mvc.Async.<>c__DisplayClass37.<BeginInvokeActionMethodWithFilters>b__31(AsyncCallback asyncCallback, Object asyncState) +191
   System.Web.Mvc.Async.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +130
   System.Web.Mvc.Async.AsyncControllerActionInvoker.BeginInvokeActionMethodWithFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor, IDictionary`2 parameters, AsyncCallback callback, Object state) +197
   System.Web.Mvc.Async.<>c__DisplayClass25.<BeginInvokeAction>b__1e(AsyncCallback asyncCallback, Object asyncState) +446
   System.Web.Mvc.Async.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +130
   System.Web.Mvc.Async.AsyncControllerActionInvoker.BeginInvokeAction(ControllerContext controllerContext, String actionName, AsyncCallback callback, Object state) +302
   System.Web.Mvc.<>c__DisplayClass1d.<BeginExecuteCore>b__17(AsyncCallback asyncCallback, Object asyncState) +30
   System.Web.Mvc.Async.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +130
   System.Web.Mvc.Controller.BeginExecuteCore(AsyncCallback callback, Object state) +382
   System.Web.Mvc.Async.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +130
   System.Web.Mvc.Controller.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state) +317
   System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state) +15
   System.Web.Mvc.<>c__DisplayClass8.<BeginProcessRequest>b__2(AsyncCallback asyncCallback, Object asyncState) +71
   System.Web.Mvc.Async.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +130
   System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +249
   System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) +50
   System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +16
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +301
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155

person angularsen    schedule 07.10.2012    source источник


Ответы (3)


Мне кажется, вы можете страдать от отсутствия двойного экранирования (сделайте \\v11.0 вместо \v11.0), как обсуждалось в этот пост.

person Krzysztof Kozielczyk    schedule 07.10.2012
comment
Я вижу, что мой вопрос был не точен, я не создал строку подключения на C#. Он был определен как ключ-значение в файлах конфигурации развертывания Azure. Так что это, к сожалению, не будет иметь значения. Я поддержу ваши усилия, спасибо. - person angularsen; 07.10.2012
comment
Спасибо. Я рад, что вы поняли это ниже. - person Krzysztof Kozielczyk; 08.10.2012

Мне стыдно осознавать, что у меня была опечатка в строках подключения. Я получал строки подключения из файлов конфигурации развертывания Azure, например:

<Setting name="SqlConnectionString" value="Server=Data Source=(LocalDb)\v11.0;Initial Catalog=aspnet-********;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnet-********.mdf" />

Опечатка была включена здесь, в начале строки значения. Должно быть, это ошибка копирования и вставки.

Эта строка была продублирована в файлах конфигурации Azure Local.cscfg и Cloud.cscfg для эмулятора Azure и развертывания Azure соответственно, а также в файле web.config для локального запуска вне эмулятора. Опечатка была только в файле Local.cscfg, что меня сильно смутило, когда я пытался понять, почему он не работал в определенных сценариях. Кроме того, мне было почему-то очень трудно обнаружить опечатку. Оглядываясь назад, я не понимаю, как я не понял этого раньше.

person angularsen    schedule 07.10.2012

У меня пока нет решения, но вот мое собственное исследование и теория:

Я взглянул на исходный код WebSecurity.InitializeDatabaseConnection() и подумал, что, возможно, нашел ошибку. Кажется, он никогда не устанавливает свойство DatabaseConnectionInfo.Type, которое по умолчанию имеет значение ConnectionStringName, что может объяснить, почему ему не нравится моя строка подключения, поскольку вместо этого оно будет интерпретировать ее как имя строки подключения.

Класс WebSecurity:

public static void InitializeDatabaseConnection(string connectionString, string providerName, string userTableName, string userIdColumn, string userNameColumn, bool autoCreateTables)
{
  WebSecurity.InitializeProviders(new DatabaseConnectionInfo()
  {
    ConnectionString = connectionString,
    ProviderName = providerName
  }, userTableName, userIdColumn, userNameColumn, autoCreateTables);
}

Класс DatabaseConnectionInfo:

public Database Connect()
{
  switch (this.Type)
  {
    case DatabaseConnectionInfo.ConnectionType.ConnectionStringName:
      return Database.Open(this.ConnectionStringName);
    case DatabaseConnectionInfo.ConnectionType.ConnectionString:
      return Database.OpenConnectionString(this.ConnectionString, this.ProviderName);
    default:
      return (Database) null;
  }
}

private enum ConnectionType
{
  ConnectionStringName,
  ConnectionString,
}
person angularsen    schedule 07.10.2012
comment
Я могу подтвердить наблюдаемое поведение ОП. Для любого, кто сталкивается с этим, несмотря на то, что имена аргументов API намекают на то, что либо может быть передана строка подключения, либо имя строки подключения, это, к сожалению, , кажется, работает только с именами строк подключения. В результате в текущей версии Simple Membership API невозможно использовать Azure CloudConfigurationManager для разрешения значения. Моя цель состояла в том, чтобы удалить настройки строки подключения в Web.config, но безуспешно. - person Bill Craun; 15.04.2013