0

我正在使用“开箱即用”的 ASP.NET MVC 4 SimpleMembership。

我在控制器上将身份验证要求设置为 deco[Authorize(Roles = "User")].

它工作正常,除非在没有注销的情况下离开网站。下一次回来,Request.IsAuthenticated还是这样,但是当我去一个视图时,我得到“ A network-related or instance-specific error occurred while establishing a connection to SQL.”实际上,它看起来像是在尝试连接到本地数据库:"SQLExpress database file auto-creation error'- 在 App_Data 文件夹中。但是我没有指向这个的连接字符串,它都在 Azure Sql 上。

知道这是什么吗?为什么它假装保持登录状态?为什么要尝试创建数据库?

------------------------------------Stack trace-------------------------------------------

[SqlException (0x80131904): A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces, error: 26 - Error Locating Server/Instance Specified)]
   System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) +5296071
   System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) +558
   System.Data.SqlClient.TdsParser.Connect(ServerInfo serverInfo, SqlInternalConnectionTds connHandler, Boolean ignoreSniOpenTimeout, Int64 timerExpire, Boolean encrypt, Boolean trustServerCert, Boolean integratedSecurity, Boolean withFailover) +5308555
   System.Data.SqlClient.SqlInternalConnectionTds.AttemptOneLogin(ServerInfo serverInfo, String newPassword, SecureString newSecurePassword, Boolean ignoreSniOpenTimeout, TimeoutTimer timeout, Boolean withFailover) +145
   System.Data.SqlClient.SqlInternalConnectionTds.LoginNoFailover(ServerInfo serverInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString connectionOptions, SqlCredential credential, TimeoutTimer timeout) +889
   System.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist(TimeoutTimer timeout, SqlConnectionString connectionOptions, SqlCredential credential, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance) +307
   System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, SqlCredential credential, Object providerInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString userConnectionOptions) +434
   System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection, DbConnectionOptions userOptions) +5311099
   System.Data.ProviderBase.DbConnectionFactory.CreateNonPooledConnection(DbConnection owningConnection, DbConnectionPoolGroup poolGroup, DbConnectionOptions userOptions) +38
   System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection) +5313314
   System.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions) +143
   System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry) +83
   System.Data.SqlClient.SqlConnection.Open() +96
   System.Web.Management.SqlServices.GetSqlConnection(String server, String user, String password, Boolean trusted, String connectionString) +76

[HttpException (0x80004005): Unable to connect to SQL Server database.]
   System.Web.Management.SqlServices.GetSqlConnection(String server, String user, String password, Boolean trusted, String connectionString) +131
   System.Web.Management.SqlServices.SetupApplicationServices(String server, String user, String password, Boolean trusted, String connectionString, String database, String dbFileName, SqlFeatures features, Boolean install) +89
   System.Web.Management.SqlServices.Install(String database, String dbFileName, String connectionString) +27
   System.Web.DataAccess.SqlConnectionHelper.CreateMdfFile(String fullFileName, String dataDir, String connectionString) +386
4

2 回答 2

0

如果您使用 SimpleMembership“开箱即用”设置,它会使用 cookie 保持用户登录。SimpleMembership 使用 EF 代码优先,如果它认为数据库不存在,它将尝试创建一个数据库。它使用延迟加载机制,因此在您点击 AccountController 之前它不会尝试创建它(即您被带到登录或注册页面)。如果授权失败,您将被重定向到登录页面。如果您使用“开箱即用”设置,那么它希望使用 web.config 中名为 DefaultConnection 的连接字符串。它看起来像这样

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

其中 ProjectName 是您第一次使用 MVC 4 Internet 模板创建 MVC 项目时的名称。您将需要更改此设置以使用 Azure。

2013 年3 月 7 日更新 由于您没有使用默认连接字符串,因此您需要更新在两个地方使用的连接字符串。你提到你在初始化程序中更新了它,所以我假设你的意思是在 SimpleMembershipInitializer 中,它的代码看起来像这样。

    public SimpleMembershipInitializer()
    {
        Database.SetInitializer<UsersContext>(null);

        try
        {
            using (var context = new UsersContext())
            {
                if (!context.Database.Exists())
                {
                    // Create the SimpleMembership database without Entity Framework migration schema
                        ((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
                }
            }

            WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
        }
        catch (Exception ex)
        {
            throw new InvalidOperationException("The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.microsoft.com/fwlink/?LinkId=256588", ex);
        }

我假设(因为您没有在问题中提供任何代码)您更新了 InitializeDatabaseConnection 中的第一个参数以使用您的连接字符串的名称。这很好,但它只处理配置数据库连接。如果您查看检测数据库是否已创建并实际创建它的代码,则高于设置此连接。连接字符串也在 UserContext 中设置,您可以在 AccountModels.cs 中找到它。代码是

public UsersContext()
    : base("DefaultConnection")
{
}

如您所见,连接字符串被传递到基本上下文。如果您没有在此处更改它,那么它将使用 DefaultConnection 连接字符串检查是否存在并尝试创建它。我相信如果缺少连接字符串,它将尝试创建一个名为 DefaultConnection 的本地数据库。

如果您使用表单身份验证,我建议您删除初始化程序并按照本文所述自行处理。这个初始化器被设计成模板生成的代码可以在开发人员不想使用表单身份验证的情况下工作。

于 2013-03-06T20:21:36.730 回答
0

我终于想通了这个问题!当我找到这个帖子时,我遇到了同样的问题,但由于没有明确的答案,我不得不自己四处寻找。

发生的情况是 UsersContext 最终将失去对其连接的跟踪。通过完全绕过 UserContext 并避免构造函数,连接将保持稳定。

注意:我不再自动生成简单的成员资格表,所以我不确定如果是这样的话这是否会奏效。

请在此处查看 AccountModels.cs 中的 UsersContext。您应该注释掉/删除此代码。

public class UsersContext : DbContext
{
    public UsersContext()
        : base("YourDBContext")
    {
    }

    public DbSet<UserProfile> UserProfiles { get; set; }
    public DbSet<webpages_Membership> webpages_Memberships { get; set; }
    public DbSet<UsersInRole> webpages_UsersInRoles { get; set; }
    public DbSet<Role> webpages_Roles { get; set; }
}

将来自 UsersContext 的 DbSet 添加到您自己的上下文中:

public class YourDBContext : DbContext
{
    public DbSet<Blah> Blahs{ get; set; }
    public DbSet<Something> Somethings { get; set; }

    public DbSet<UserProfile> UserProfiles { get; set; }
    public DbSet<webpages_Membership> webpages_Memberships { get; set; }
    public DbSet<UsersInRole> webpages_UsersInRoles { get; set; }
    public DbSet<Role> webpages_Roles { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
    }

}

当然,在您完成所有操作后,您必须将对 UsersContext 的任何引用更改为 YourDBContext,即

UsersContext uc = new UsersContext();

变成

YourDBContext ydb = new YourDBContext();

这样做的额外好处是您不必跟踪两个不同的 DBContext。

于 2013-08-20T20:45:02.280 回答