c# - 扩展 ApplicationUser 如何从共享项目中正确设置关系

标签 c# asp.net entity-framework

我正在使用 ASP.NET Identity 2.0。目前我想通过表 UserDetails 扩展 ApplicationUser (将 AspNetUsers 重命名为 Users),如 FirstName 等等

我的问题是什么? 我已经分离了存储 EF 模型的类库项目。我不喜欢生成另一个 EF 模型(如果没有必要)。

我在 SQL Server 中的用户表和UserDetails 表之间有关系,没关系。不幸的是,在 ASP 项目中,Users 表在 IdentityUser 中深度硬编码。这意味着我有继承 IdentityUserApplicationUser

我正在尝试的是在AppDbContext中:

protected override void OnModelCreating(ModelBuilder builder)
{
    base.OnModelCreating(builder);

    // Ignore columns
    builder.Entity<ApplicationUser>().Ignore(c => c.PhoneNumberConfirmed);

    // Rename tables
    builder.Entity<ApplicationUser>().ToTable("Users");
    builder.Entity<IdentityRole>().ToTable("Roles");
    builder.Entity<IdentityRoleClaim<string>>().ToTable("IdentityRoleClaims");
    builder.Entity<IdentityUserClaim<string>>().ToTable("IdentityUserClaims");
    builder.Entity<IdentityUserLogin<string>>().ToTable("IdentityUserLogins");
    builder.Entity<IdentityUserToken<string>>().ToTable("IdentityUserTokens");

    // Relationship
    builder.Entity<ApplicationUser>()
        .HasOne(p => p.UserDetails)
        .WithOne(i => i.Users)
        .HasForeignKey<Shared.Database.UserDetails>(u => u.UserID);
}

问题出在 WithOne(i => i.Users) 的最后一行,i.Users 不是 ApplicationUser。有趣的是, ApplicationUser 具有与 i.Users 相同的属性:D

所以我只需要知道如何正确地转换它来建立关系。

有什么想法可以解决这个问题吗?或者有什么建议如何以另一种方式做到这一点?

共享项目由 1 个附加项目 (WCF) 使用,因此我无法将其继承自 IdentityUser :/

谢谢大家。

最佳答案

按照我的理解,您希望将两个不同的对象映射到同一个数据库表,并将另一个实体 FK 映射到该表。 Adn 您对第一部分没有问题,但对第二部分有问题:

Problem is on last line in WithOne(i => i.Users), i.Users is not ApplicationUser. Funny thing is that ApplicationUser has same properties like i.Users :D

我看到两种解决方案。

  1. UserDetails 类中删除导航属性,并在两个地方使用 WithOne()
  2. 如果您需要该导航属性,可以使用类似于 Identity 类结构的方法,如下所示:

假设您当前在共享项目中的 UserDetails 类如下所示:

public class UserDetails
{
    public string Id { get; set; }
    public string FirstName { get; set; }
    // other properties ...
    public string UserID { get; set; }
    public User User { get; set; } // the problematic navigation property
}

您可以将其转换为泛型类:

public class UserDetails<TUser> where TUser: class
{
    public string Id { get; set; }
    public string FirstName { get; set; }
    // other properties ...
    public string UserId { get; set; }
    public TUser User { get; set; }
}

并让旧的非泛型类简单地继承它:

public class UserDetails : UserDetails<User> { } 

现在共享项目 EF 模型中的所有内容都应与以前一样,因此使用它的其他 (WCF) 项目不应受到影响。

我想您已经明白了。在 ASP 项目中,您只需创建另一个类:

public class ApplicationUserDetails : UserDetails<ApplicationUser> { }

并将其映射到 UserDetails 表,类似于将 ApplicationUser 映射到 Users:

builder.Entity<ApplicationUserDetails>().ToTable("UserDetails");

然后将 ApplicationUser 类中的 UserDetails 导航属性更改为:

public ApplicationUserDetails UserDetails { get; set; }

最终建立了没有任何问题的关系:

builder.Entity<ApplicationUser>()
    .HasOne(u => u.UserDetails)
    .WithOne(d => d.User)
    .HasForeignKey<ApplicationUserDetails>(d => d.UserID);

关于c# - 扩展 ApplicationUser 如何从共享项目中正确设置关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42507836/

相关文章:

asp.net - Telerik RadEditor HTTP POST VALUE 未更新(ASP.NET Web 表单)

php - 在 php/asp.net 应用程序中保存/加载 img/文件(word、excel 等)的最佳方法是什么?

c# - EF6 可选 1 :1 include not working

c# - nlog 不创建文件

c# - 在 C# 中使用 `using` 关键字避免多次处置的最佳实践

c# - Linq-to-Sql:递归获取 child

c# - T4模板多次处理输入

c# - 包含内容的 Web 用户控件

c# - 如何更改 Entity Framework 为 Datetime 生成 SQL 精度的方式

entity-framework - 属性X的类型为Y,当前数据库提供程序不支持该属性