如何将现有数据库的ASP.NET MVC站点部署到Azure Web Apps?

时间:2016-11-19 23:37:45

标签: asp.net-mvc asp.net-mvc-4 azure azure-web-sites azure-web-app-service

问题结构:首先,我给出了ASP-MVC-4项目的结构和配置,然后描述了我如何将我的网站部署到Azure Web Apps,最后提出了我的错误和问题。我的问题与Azure部署期间与EF Code-First Migrations的冲突有关。

我的ASP MVC 4项目和配置:

我正在使用 Visual Studio 2015-U3 。我有 ASP.NET MVC 4 网站。目标框架:.NET Framework 4.5。该站点拥有自己的数据库,可在本地运行并与数据库((LocalDb)\v11.0)进行交互。我使用Entity Framework Code-First方法来创建和填充数据。

Web.config中的我的数据库连接字符串

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

(在发布上替换,但以防万一)

我的DbContext课程:

    public partial class AuctionDataContext : DbContext
    {       
        public AuctionDataContext() : base("DefaultConnection") 
        {    }

        public DbSet<Auction> Auctions { get; set; }
        public DbSet<Category> Categories { get; set; }
        public DbSet<User> Users { get; set; }
        public DbSet<Order> Orders { get; set; }
        public DbSet<Bid> Bids { get; set; }
        public DbSet<ItemImage> Images { get; set; }
        public DbSet<Detail> Details { get; set; }
        public DbSet<DetailValue> DetailValues { get; set; }
   }

我有DataContextInitializer类,我在其中初始化所有需要的数据。

 public class DataContextInitializer : DropCreateDatabaseAlways<AuctionDataContext>
    {
        protected override void Seed(AuctionDataContext context)
        { 
           ***All my initializations go here 
        }
    }

由于我没有使用普通 SQL ,而是使用实体框架代码优先,我启用了迁移。在Configuration类和 Configuration.cs 文件中,我写道:

 public Configuration()
        {
            AutomaticMigrationsEnabled = true;
        }

部署到Azure

现在我切换到 Azure Web Apps 的部署。我使用发布按钮将站点部署到Azure网站。

步骤一步:

我选择了Microsoft Azure Web Apps:

enter image description here

然后我选择了我创建的网站 auctionWeb (这里的所有内容都是自动设置的):

enter image description here

在下一步我只选择了Execute Code First Migrations连接字符串(默认连接)已自动设置 。它被设置为:

Data Source=tcp:auction-tserver.database.windows.net,1433;Initial Catalog=OnlineAuctionDb;User Id=auctionAdmin@auction-tserver.database.windows.net;Password=mypassword

enter image description here

在最后一步中,我点击发布按钮:

enter image description here

浏览器输出:

我收到错误

  '/'应用程序中的服务器错误。   无效的列名称'FirstName'。列名称“LastName”无效。列名称“电子邮件”无效。列名称“国家/地区”无效。无效   列名称“State”。列名称“城市”无效。列名无效   '地址'。列名称“PostalCode”无效。列名无效   '电话'。列名称“密码”无效。

     

描述:在执行当前Web请求期间发生了未处理的异常。请查看堆栈跟踪了解更多信息   有关错误的信息以及它在代码中的起源。

     

源错误:在执行当前Web请求期间生成了未处理的异常。有关原产地的信息   可以使用异常来识别异常的位置   堆栈跟踪下面。

堆栈跟踪:

[SqlException (0x80131904): Invalid column name 'FirstName'.
Invalid column name 'LastName'.
Invalid column name 'Email'.
Invalid column name 'Country'.
Invalid column name 'State'.
Invalid column name 'City'.
Invalid column name 'Address'.
Invalid column name 'PostalCode'.
Invalid column name 'Phone'.
Invalid column name 'Password'.]
   System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) +2442634
   System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) +5766568
   System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) +285
   System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady) +4162
   System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString, Boolean isInternal, Boolean forDescribeParameterEncryption) +255
   System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, Boolean inRetry, SqlDataReader ds, Boolean describeParameterEncryptionRequest) +2031
   System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry) +911
   System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry) +359
   System.Data.SqlClient.SqlCommand.ExecuteNonQuery() +286
   WebMatrix.Data.Database.Execute(String commandText, Object[] args) +111
   WebMatrix.WebData.DatabaseWrapper.Execute(String commandText, Object[] parameters) +14
   WebMatrix.WebData.SimpleMembershipProvider.CreateUserRow(IDatabase db, String userName, IDictionary`2 values) +695
   WebMatrix.WebData.SimpleMembershipProvider.CreateUserAndAccount(String userName, String password, Boolean requireConfirmation, IDictionary`2 values) +65
   WebMatrix.WebData.WebSecurity.CreateUserAndAccount(String userName, String password, Object propertyValues, Boolean requireConfirmationToken) +70
   OnlineAuction.MvcApplication.SetSecurityOptions() +322
   OnlineAuction.MvcApplication.Application_Start() +51

[HttpException (0x80004005): Invalid column name 'FirstName'.
Invalid column name 'LastName'.
Invalid column name 'Email'.
Invalid column name 'Country'.
Invalid column name 'State'.
Invalid column name 'City'.
Invalid column name 'Address'.
Invalid column name 'PostalCode'.
Invalid column name 'Phone'.
Invalid column name 'Password'.]
   System.Web.HttpApplicationFactory.EnsureAppStartCalledForIntegratedMode(HttpContext context, HttpApplication app) +9982013
   System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS(IntPtr appContext, HttpContext context, MethodInfo[] handlers) +118
   System.Web.HttpApplication.InitSpecial(HttpApplicationState state, MethodInfo[] handlers, IntPtr appContext, HttpContext context) +172
   System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(IntPtr appContext, HttpContext context) +336
   System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr appContext) +296

[HttpException (0x80004005): Invalid column name 'FirstName'.
Invalid column name 'LastName'.
Invalid column name 'Email'.
Invalid column name 'Country'.
Invalid column name 'State'.
Invalid column name 'City'.
Invalid column name 'Address'.
Invalid column name 'PostalCode'.
Invalid column name 'Phone'.
Invalid column name 'Password'.]
   System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +9963380
   System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +101
   System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +254

问题:

为什么我收到错误?当我使用EF Code-first时,如何将ASP.NET MVC 4网站正确部署到Microsoft Azure Web Apps云,以便数据库和站点协同工作。在localhost一切正常。

更新1:

当我在Azure门户中设置我的数据库并打开数据库连接字符串时,我看到这个字符串:

Server=tcp:auction-tserver.database.windows.net,1433;Initial Catalog=OnlineAuctionDb;Persist Security Info=False;User ID={your_username};Password={your_password};MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;

enter image description here

但是当我将此字符串(具有正确的登录名和密码)设置为我的连接字符串的Web App设置时,我仍然会收到相同的错误页面。

更新2:

Application_Start()方法的 Global.asax 文件中,我 这行代码:

 System.Data.Entity.Database.SetInitializer(new OnlineAuction.Models.Entities.DataContextInitializer());

现在我将其更改为:

System.Data.Entity.Database.SetInitializer(new System.Data.Entity.MigrateDatabaseToLatestVersion<AuctionDataContext, Configuration>());

我将所有初始化从DataContextInitializer类移到Configuration类(Seed()方法)。

所以我的DataContextInitializer看起来像这样:

 public class DataContextInitializer : DropCreateDatabaseAlways<AuctionDataContext>
        {
            protected override void Seed(AuctionDataContext context)
            { 
               ***All my initializations go here 
            }
        }
不再需要

。因此,ConfigurationDataContextInitializer类不再发生冲突。

现在,我的所有初始化都在Configuration类:

   public class Configuration : DbMigrationsConfiguration<OnlineAuction.Models.Entities.AuctionDataContext>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = false;
        }

        protected override void Seed(AuctionDataContext context)
        { 
            ***All my initializations go here 
        }
    }

我还设置为 false AutomaticMigrationsEnabled选项。

但我不确定在网站Execute Code First Migrations (runs on application start)过程中如何处理复选框Publish。我现在必须关掉它吗?

我对所有代码优先的迁移冲突感到困惑。它仍然无效。

1 个答案:

答案 0 :(得分:4)

根据您提供的Stack Trace,我假设您没有正确迁移数据库表。根据您链接的源代码,我可以在将网站部署到Azure后重现您的问题。这是我的Azure SQL上的数据库表。

注意:根据屏幕截图,我们可以看到Users表中只有两个属性。

经过一些试验,我可以成功将我的网站部署到Azure。您可以按照以下步骤操作,尝试查找是否可以按预期工作。

如您所述,修改Application_Start下面的数据库初始化策略:

System.Data.Entity.Database.SetInitializer(new System.Data.Entity.MigrateDatabaseToLatestVersion<AuctionDataContext, Configuration>());

将函数SetSecurityOptions中的初始化移动到Seed()类中Configuration函数的底部。

注意:由于您已启用迁移,因此您需要将待处理的模型更改添加到基于代码的迁移中,或启用自动迁移以更新数据库。因此,您需要将DbMigrationsConfiguration.AutomaticMigrationsEnabled设置为true以启用自动迁移。

结果:http://bruce-chen-001.azurewebsites.net/

此外,请按照Russell Young提供的tutorial更好地了解Code First Migrations。