【问题标题】:What binds ApplicationUser to the aspnetusers table in Database First?是什么将 ApplicationUser 绑定到 Database First 中的 aspnetusers 表?
【发布时间】:2015-03-26 16:44:43
【问题描述】:

我在一个单独的库(例如 Common.Feedback.Data)中有一个数据库优先的 EDMX 模型,其中包括 AspNetUser 表及其相关的身份框架表(从另一个现有的、正在工作的数据库/应用程序中提取)。

我已更新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" />

在运行时,任何对登录的访问都会导致以下错误:

“实体类型 ApplicationUser 不是当前上下文模型的一部分”

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

我无法启用迁移,因为它是 EDMX 首次设置,但我假设 ApplicationUser 对象和 aspnetusers 表在幕后“某处”之间存在绑定。

这里有没有人清楚地了解ApplicationUser 类在运行时如何映射到aspnetusers 表/从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 和this link 的建议更新了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>

新更新:

我使用标准 user-security 选项创建了一个全新的 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 流。

来源错误:

第 153 行:{ 第 154 行:var user = new ApplicationUser { 用户名 = model.Email,Email = model.Email };线 155: var 结果 = 等待 UserManager.CreateAsync(用户, 型号.密码);第 156 行:if (result.Succeeded) 行 157:{

【问题讨论】:

  • 如果您采用 DB-first 解决方案的路线,则没有理由坚持使用 ApplicationDbContext。您可以删除所有垃圾,拥有自己的 DbContext 并省去自己的头疼
  • 您只展示了 ApplicationDbContext() 的构造函数,您可以展示整个类。另外,您使用的是哪个版本的身份?版本 1.0 与版本 2 完全不同。通过 EntityTypeConfiguration 的子类在类和表之间进行映射,您可以在其中设置模型的各个方面,例如映射参照完整性、基数等。如果您在 TspIdentityMap 中使用 Fluent Api:EntityTypeConfiguration 你会做出这样的声明。ToTable("AspNetUsers");即您将代码类实体 TspIdentity 映射到 db 表。
  • 我想看到你的整个 ApplicationDbContext 的原因是,我读到的消息就像你的上下文中没有 DbSet 一样,但我通常会产生编译器错误......但是你已经混合和匹配了位,所以让我们看看都一样。还要检查您在所有项目中是否使用相同版本的 Identity。
  • @rism:我应该说,一切都是“开箱即用”的 Visual Studio 2013 脚手架 + MVC5 Razor 以及最新版本的“一切”。在我解决此问题之前,这目前只是一个简单的项目。
  • 在默认项目的 web.config 中

标签: c# asp.net-mvc entity-framework-6 asp.net-identity ef-database-first


【解决方案1】:

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

我使用 DotPeek 反编译了 Identity Framework dll,发现表名“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 查询的名称/值的简单映射。

至于问题的另一部分,数据库连接,我创建了一个新问题,因为它 a) 与这个问题的标题无关 b) 让我发疯!问题是Why am I getting "The magic number in GZip header is not correct." error using OWIN auth against Azure SQL

【讨论】:

    猜你喜欢
    • 2019-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多