【问题标题】:Why is my Custom Object Property in ApplicationUser null?为什么我在 ApplicationUser 中的自定义对象属性为空?
【发布时间】:2015-06-08 04:19:26
【问题描述】:

我创建了一个名为Person 的自定义类来存储姓名、地址等。这个类/模型与其他模型交叉引用,包括ApplicationUser

public class ApplicationUser : IdentityUser
{
    public Person Person { get; set; }

    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;
    }
}

在我的一个控制器中,我使用以下代码让当前用户登录并获取它的 Person 对象,如下所示:

        var user = UserManager.FindById(User.Identity.GetUserId());
        var person = user.Person;

我的Person类也在ApplicationDbContext中定义:

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

    public DbSet<Person> People { get; set; }
}

当我检查 user 时,我可以看到 Entity Framework 填充了该对象,因为我看到了用户 ID、电子邮件地址、密码哈希等所有内容!所有除了 Person 属性!但是,我可以在数据库中看到对应的行不是null,而是Person 的正确ID。

我是 ASP.NET/MVC/Entity 框架的新手,我读到它默认使用延迟加载。这是我正在经历的吗?如果是这样,我如何告诉 Entity 在Person 属性上使用预先加载?如果没有,我做错了什么?

【问题讨论】:

  • 确保在UserManager.FindById方法中分配Person属性...
  • 1) 您是否在ApplicationDbContext 中添加了IDbSet&lt;Person&gt;? & 2) 尝试将 ApplicationUser.Person 属性标记为虚拟(以便代理类可以延迟加载它)。 -- 在我看来,数据库不知道它作为一种关系存在,可能需要使用隐式约定/属性/流式模型绑定来告诉 EF。
  • @BradChristie 1) 是的,我在ApplicationDbContext 中定义了它。 2)我会尝试将其标记为虚拟。

标签: c# asp.net asp.net-mvc entity-framework asp.net-mvc-5


【解决方案1】:

这可能是映射问题。实体框架映射太复杂了,我无法在这里解释,但我会指出问题可能出在哪里。

确保ApplicationUser 具有Person 的外键属性,并且实体框架可以理解它。实体框架是基于约定的,因此默认情况下它将在您的 ApplicationUser 类中查找 PersonId 属性。如果您不想使用默认名称,您可以在 Context 的 OnModelCreating 上使用流利的配置来给它一个自定义名称。

我个人认为手动映射所有关系总是一个好主意。这是一个例子:

public void OnModelCreating(ModelBuilder modelBuilder)
{
    builder.Entity<ApplicationUser>().HasRequired(m => m.Person).HasForeignKey(d => d.Person) 
}

更多信息请参考此链接:https://msdn.microsoft.com/en-us/data/jj591620.aspx

【讨论】:

  • 嗯,成功了!我将modelBuilder.Entity&lt;ApplicationUser&gt;().HasOptional(m =&gt; m.Person); 添加到我的OnModelCreating 方法中,现在它可以工作了。感谢您的帮助,@andrerpena!但是,我仍然不明白为什么Entity Framework之前成功地将数据正确插入到数据库中,但没有读取它。我认为插入也会失败。
  • 我很高兴结果很好。 Entity Framework 正确插入数据是因为它承认 Person 的存在,但不承认它与 ApplicationUser 的关系。
【解决方案2】:

我会让 Person 类继承自 IdentityUserApplicationUser。然后,我将在 dbcontext 类中包含以下内容:

DbSet<Person> People {get;set;}

那么你可以使用这个:

MyDbContext db = new MyDbContext();    
string userid = User.Identity.GetUserId();
var user = db.People.Single(p=>p.Id == userid );

【讨论】:

  • 或者他可以在ApplicationUser类中添加所有Person的属性。
  • 我的Person 类也被我项目中的其他类使用,这些类不一定是ApplicationUsers,所以我无法继承它。
【解决方案3】:

在实体框架代码优先方法中,实体框架将第一个整数属性作为主键。所以在这里你在应用程序 User 类中添加 Person 类的引用。你可以试试这个:

[ForeignKey("PersonId")]

公共虚拟人 Person{get;set;}

public int PersonId{get;set;}

这将使 PersonId 成为应用程序用户表中的外键。您也可以使其为空

公共整数? PersonId{get;set;}

从那里您可以获取插入到应用程序用户表中的 Person 对象的 Id,然后您可以获取该 person 对象的属性。

我希望这对您有所帮助,因为它映射了两个表之间的关系。

【讨论】:

    猜你喜欢
    • 2020-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-10
    • 2012-01-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多