什么将ApplicationUser与Database First中的aspnetusers表绑定?

10

我在一个单独的库中(例如Common.Feedback.Data)有一个基于数据库的EDMX模型,其中包括AspNetUser表及其相关的Identity Framework表(从另一个现有的、可工作的数据库/应用程序中提取)。

我已经更新了ApplicationDbContext连接字符串,使其指向新的模型和新的数据库连接:

using System.Data.Entity;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;

namespace Feedback.MvcApplication.Models
{
    // You can add profile data for the user by adding more properties to your ApplicationUser class, please visit http://go.microsoft.com/fwlink/?LinkID=317594 to learn more.

    public class ApplicationUser : IdentityUser
    {
        public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
        {
            // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
            var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
            // Add custom user claims here
            return userIdentity;
        }
    }

    public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
        public ApplicationDbContext()
            : base("FeedbackEntities", throwIfV1Schema: false)
        {
        }

        public static ApplicationDbContext Create()
        {
            return new ApplicationDbContext();
        }
    }
}

在 web.config 中的连接字符串包括了程序集的完整路径,该引用是正确的:

<add name="FeedbackEntities" 
     connectionString="metadata=res://Common.Feedback.Data/FeedbackModel.csdl|res://Common.Feedback.Data/FeedbackModel.ssdl|res://Common.Feedback.Data/FeedbackModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=mydatabase.database.windows.net;initial catalog=Feedback;persist security info=True;user id=LeaveFeedbackuser@mydatabase;password=mypassword;MultipleActiveResultSets=True;App=EntityFramework&quot;" 
     providerName="System.Data.EntityClient" />

运行时,任何访问登录页面的操作都会导致以下错误:

"The entity type ApplicationUser is not part of the model for the current context"

我尝试了所有与该错误相关的链接,通常涉及更新迁移的方式。

由于这是一个EDMX首次设置,我无法启用迁移。但是,我认为ApplicationUser对象和aspnetusers表之间“某处”有绑定关系。

这里是否有人清楚地了解如何在运行时将ApplicationUser类映射到aspnetusers表,并解释如何使我的代码与数据库一起工作?

复制步骤

  • 使用VS 2013创建新的MVC Web应用程序
  • 将所有NuGet包更新到最新版本
  • 拷贝现有的带Identity Framework表的SQL数据库到新表(删除任何不相关的表)
  • 添加项目的新表
  • 创建一个类库来保存数据模型(例如:Common.Feedback.Data
  • 基于先前创建的数据库,在库中添加Edmx数据模型
  • 更改连接字符串以完全限定程序集(不使用res://*/
  • IdentityModel.cs中更改连接字符串名称,以匹配配置文件中的连接字符串名称。
  • 从库的app.config复制连接字符串到Web项目的web.config
  • 尝试登录,您将遇到上述错误

更新:

根据一个杂散的帖子,我将我的连接字符串更改为与默认情况下Identity Framework配置使用的普通SQL连接匹配(并使用Sql客户端):

<add name="FeedbackSql" 
     connectionString="data source=mydatabase.database.windows.net;initial catalog=Feedback;persist security info=True;user id=LeaveFeedbackuser@mydatabase;password=mypassword;MultipleActiveResultSets=True;App=EntityFramework" 
     providerName="System.Data.SqlClient" />

并且修改设置以使用这个新连接:

   public ApplicationDbContext()
        : base("FeedbackSql", throwIfV1Schema: false)
    {
    }

出现了奇怪的错误:

GZip头中的魔术数字不正确。确保您正在传入GZip流。

我认为更改为 SqlClient 提供程序是正确的,所以这个新错误可能与在该连接上使用 Azure 数据库有关。我愿意尝试下一步要尝试什么。

根据 @rism 的建议和 这个链接 更新了 web.config(但 GZip 错误仍然存在):

  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework">
      <parameters>
        <!--<parameter value="mssqllocaldb" />-->
        <parameter value="data source=mydatabase.database.windows.net;initial catalog=Feedback;persist security info=True;user id=myuserid;password=mypassword;MultipleActiveResultSets=True;App=EntityFramework" />
      </parameters>
    </defaultConnectionFactory>
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
  </entityFramework>

再次根据 @rism 提供的提示,我尝试了这个版本(但 GZip 错误仍然存在):

  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="v12.0" />
      </parameters>
    </defaultConnectionFactory>
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
  </entityFramework>

最新更新:

我创建了一个全新的Web应用程序,带有标准的用户安全选项。我还在Azure中创建了一个空数据库。

我仅仅改变了默认连接字符串到这个:

  <connectionStrings>
    <add name="DefaultConnection" 
         connectionString="data source=mydatabase.database.windows.net;initial catalog=Feedback;persist security info=True;user id=LeaveFeedbackuser;password=mypassword;MultipleActiveResultSets=True;App=EntityFramework"
         providerName="System.Data.SqlClient" />
  </connectionStrings>

并将默认连接工厂设置为:

  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="v12.0" />
      </parameters>
    </defaultConnectionFactory>
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
  </entityFramework>
登录时出现以下错误:
引号块: GZip头部的魔数不正确。请确保传入的是一个GZip流。 描述:在当前web请求的执行过程中发生了未处理的异常,请检查堆栈跟踪以获取有关错误及其来源代码的更多信息。
异常详细信息:System.IO.InvalidDataException:GZip头部中的魔数不正确,请确保传入的是GZip流。
源错误:
Line 153: { Line 154: var user = new ApplicationUser { UserName = model.Email, Email = model.Email }; Line 155: var result = await UserManager.CreateAsync(user, model.Password); Line 156: if (result.Succeeded) Line 157: { }

1
如果您选择使用 DB-first 解决方案,那么没有理由坚持使用 ApplicationDbContext。您可以删除所有多余的内容,拥有自己的 DbContext 并避免麻烦。 - jamesSampica
你只展示了 ApplicationDbContext() 的构造函数,能否展示整个类?另外,你使用的 Identity 版本是哪个?版本 1.0 和版本 2 相差很大。通过 EntityTypeConfiguration 的子类进行类和表之间的映射,你可以设置模型的方面,如映射引用完整性、基数等。如果你在 TspIdentityMap : EntityTypeConfiguration<TspIdentity> 中使用 Fluent Api,你会像这样声明:this.ToTable("AspNetUsers"); 即将代码类实体 TspIdentity 映射到数据库表。 - rism
@rism: 我应该说,一切都是Visual Studio 2013脚手架 + MVC5 Razor的“开箱即用”版本,并且使用了最新版本的“一切”。目前这只是一个基本项目,直到我解决这个问题为止。 - iCollect.it Ltd
在默认项目的 web.config 中,<entityFramework> 的 <defaultConnectionFactory> 将被设置为使用 LocalDb,你是否已将其更新为使用 SqlServer?并且,您能否向我们展示 YSOD 的堆栈跟踪? - rism
@TrueBlueAussie 通常情况下,您应该保留连接字符串不变,并按照以下方式更新该部分:<entityFramework> <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework"> <parameters> <parameter value="v12.0" /> </parameters> </defaultConnectionFactory> <providers> <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" /> </providers> </entityFramework> - rism
显示剩余6条评论
1个回答

14

原始问题是关于 OWIN 如何将 ApplicationUser 类映射到 AspNetUsers 表的。

我使用 DotPeek 反编译了 Identity Framework dlls 并发现表名 "AspNetUsers" 简单地硬编码在 OnModelCreating 方法的代码中。例如:

 protected virtual void OnModelCreating(DbModelBuilder modelBuilder)
    {
      if (modelBuilder == null)
        throw new ArgumentNullException("modelBuilder");
        EntityTypeConfiguration<TUser> typeConfiguration1 = ((EntityTypeConfiguration<TUser>) modelBuilder.Entity<TUser>())
        .ToTable("AspNetUsers");
那段代码使用反射从ApplicationUser的属性中生成字段名称列表。它使用一个简单的SQL查询(来自包含所有字段名称的系统表)检查所有这些字段名称是否存在,并确认它们全部存在。
其余部分是使用构建的SQL查询对名称/值进行简单的映射。
至于问题的另一部分——数据库连接,我已经创建了一个新的问题,因为它与本题的标题不相关并让我感到疯狂!新问题见:Why am I getting "The magic number in GZip header is not correct." error using OWIN auth against Azure SQL

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接