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

时间:2017-02-28 11:40:50

标签: c# asp.net entity-framework

我正在使用ASP.NET Identity 2.0。目前,我希望将ApplicationUser(已AspNetUsers重命名为Users)扩展到UserDetails等表FirstName

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

我在用户表和UserDetails表之间存在SQL Server关系,这一切都没问题。不幸的是,在ASP项目中,Users表在IdentityUser中进行了深度硬编码。这意味着我ApplicationUser继承了IdentityUser

我在尝试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:/

谢谢你们。

1 个答案:

答案 0 :(得分:2)

我理解它的方式,您希望将两个不同的对象映射到同一个数据库表,并将另一个实体FK映射到该表。你对第一部分没有任何问题,但第二部分遇到了麻烦:

  

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

我看到两种解决方案。

  1. UserDetails课程中删除导航属性,只需在WithOne()这两个地方使用。
  2. 如果您需要该导航属性,可以使用类似于Identity类结构的方法,如下所示:
  3. 假设您当前在共享项目中的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");
    

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

    public ApplicationUserDetails UserDetails { get; set; }
    

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

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