C# 如何使用Entity Framework在.NET Core中保存用户数据

C# 如何使用Entity Framework在.NET Core中保存用户数据,c#,entity-framework,.net-core,entity-framework-core,C#,Entity Framework,.net Core,Entity Framework Core,我正在使用.NETCore2.2,我在理解保存用户拥有的数据的正确方法时遇到了困难 我正在使用开箱即用的身份脚手架和代码优先迁移。 用户存储在AspNetUsers表中,我正在利用Google/Facebook提供商 作为一个基本的例子,如果我有这样一个简单的模型,我找不到一个清晰的例子来说明如何引用模型中数据的所有者 public class UserFavoriteColor { public int Id { get; set; } public string Color

我正在使用.NETCore2.2,我在理解保存用户拥有的数据的正确方法时遇到了困难

我正在使用开箱即用的身份脚手架和代码优先迁移。 用户存储在
AspNetUsers
表中,我正在利用Google/Facebook提供商

作为一个基本的例子,如果我有这样一个简单的模型,我找不到一个清晰的例子来说明如何引用模型中数据的所有者

public class UserFavoriteColor
{
    public int Id { get; set; }
    public string Color {get; set;

    public IdentityUser User { get; set; }    // I've seen this in some documentation
    public string UserId { get; set; }        // I've seen this as well
    // Other ways??
}
此外,似乎还有几种方法可以检索和存储用户信息:

// one way to get the id
User.FindFirst(ClaimTypes.NameIdentifier).Value;                   

// another way
 _userManager = MockUserManager.GetUserManager<ApplicationUser>(); 
//获取id的一种方法
User.FindFirst(ClaimTypes.NameIdentifier).Value;
//另一种方式
_userManager=MockUserManager.GetUserManager();
也许我完全忽略了一些显而易见的东西,但我希望看到一个非常基本的模型和控制器示例,它使用最佳实践方法将带有用户标识值的记录保存为外键


谢谢

如果在模型
UserFavoriteColor
中定义了外键字段
UserId
和导航属性
User
,则可以选择要设置的属性。我将使用
ForeignKey
DataAnnotation属性来进一步描述这两个字段之间的关系

如果您仅在模型中实现了
用户
导航属性,则外键字段仍将在数据库级别实现,但您将无法在代码中引用它。因此,它不是明确要求的,在许多在线示例中,我们将其简化为示例,因为许多人会考虑将模型中的外键暴露为不应该存在的实现细节… 通过控制器保存这种类型的记录是相当标准的,通常通过控制器我会设置外键字段,而不是导航属性。 它的代码更简单,并且不太容易在数据库中生成重复的条目

如果您有一个
User
对象,您可以设置该对象,而不是
UserId
,并且在保存更改时会自动解析键字段,但是
User
对象必须已从同一DbContext加载或至少已附加到同一DbContext,否则可能导致在数据库中创建新的
User
记录

为了保存对当前用户的引用,您用于检索用户Id的机制在很大程度上取决于您如何配置身份验证,这超出了本问题的范围

var currentUserId = User.FindFirst(ClaimTypes.NameIdentifier).Value;
var color = "Red";
...
// Insert a new favorite colour record
UserFavoriteColor record = new UserFavoriteColor {
    Color = color,
    UserId = currentUserId 
};
context.Add(record);
context.SaveChanges();

记住EF使用并使用它来识别主键、外键和映射

让我们考虑这个场景(见内联注释)

按照默认约定,EF将属性设置为外键 属性,当其名称与 相关实体

[ForeignKey]
依赖实体中外键属性的注释(如上例所示)
[ForeignKey]
依赖实体中导航属性的注释
[ForeignKey]
主体实体中导航属性的注释


现在添加迁移和更新数据库

  • 添加迁移AddNewUser
添加新用户

  • 更新数据库-详细
注意:在开始时,确保域类和数据模型之间有良好的分离


不寻找基本设置,尝试理解将数据记录与用户身份关联。非常好。在您的示例中,我在其他领域使用了外键结构,并倾向于使用它,但就是找不到它的琐碎文档,以确保它适用于像标识这样敏感的内容。感谢您的详细介绍和解释!我看过其他创建类似于您的示例的“IdentityUser”类的文档,但是您不应该使用内置类而不是尝试使用包装器吗?克里斯的回答似乎更有意义,不需要定义“IdentityUser”(除非我误解了你的例子)。感谢您的撰写。@EricLongstreet,您所说的“使用内置的而不是使用包装器”是什么意思?在您的示例中,您定义了类模型“IdentityUser”,然而,据我所知,这是一个内置的dotnet核心身份框架类。啊,好的,是的,你可以在它上面使用内置的脚手架,这里的要点是要注意EF core如何默认确定外键实体,以及如何覆盖它们。此外,没有必要将
id
标记为主键,因为这是由EF Cores约定推断的
var currentUserId = User.FindFirst(ClaimTypes.NameIdentifier).Value;
var color = "Red";
...
// Insert a new favorite colour record
UserFavoriteColor record = new UserFavoriteColor {
    Color = color,
    UserId = currentUserId 
};
context.Add(record);
context.SaveChanges();

public class UserFavoriteColor
{
  public int Id { get; set; }
  public string Color {get; set;


  public int UserId { get; set; } // By default convention EF will mark this as foreign key property as its name matches the primary key of related entity
  public IdentityUser User { get; set; } // Navigation property 

}

public class IdentityUser
{
  public int UserId { get; set; } // EF will treat this as Primary Key 
  public string UserName {get; set;}
  public ICollection<UserFavoriteColor> FavColors { get; set; }
}
[ForeignKey("IdentityUser")]
public int ThisUserId { get; set; }
public IdentityUser User { get; set; } 
var color1 = new UserFavoriteColor {Color="Red"}
var user = new IdentityUser {UserName="Bob",};
using  (var context = new DbContext())
{
    context.DBSetName.Add(user);  
    context.SaveChanges();
    //Save changes will - Examine each object context is tracking
                        - Read state of object (state=new) therefore needs to Insert
                        - Emit SQL commands
                        - Execute SQL commands
                        - Captures any results
}