C# .NET MVC Core 2.2-Can';t访问用户相关实体(外键)
我正在MVC Core 2中编写我自己的第一个应用程序,我在访问具有用户外键的地产实体时遇到问题。我已检查我的数据库,房地产记录正确存储用户ID: 当我尝试获取C# .NET MVC Core 2.2-Can';t访问用户相关实体(外键),c#,asp.net-core,.net-core,asp.net-identity,entity-framework-core,C#,Asp.net Core,.net Core,Asp.net Identity,Entity Framework Core,我正在MVC Core 2中编写我自己的第一个应用程序,我在访问具有用户外键的地产实体时遇到问题。我已检查我的数据库,房地产记录正确存储用户ID: 当我尝试获取context.Estates.FirstOrDefault(m=>m.Id==Id)时我得到一个地产实体,但带有User==null: 当我尝试通过以下方式访问它时: var user = await _userManager.GetUserAsync(User); var estate = user.Estates.FirstOr
context.Estates.FirstOrDefault(m=>m.Id==Id)时代码>我得到一个地产实体,但带有User==null
:
当我尝试通过以下方式访问它时:
var user = await _userManager.GetUserAsync(User);
var estate = user.Estates.FirstOrDefault(m => m.Id == id);
我在不动产清单上得到空的例外。同样尝试以这种方式保存它也会给我一个例外:
var user = await _userManager.GetUserAsync(User);
user.Estates.Add(estate);
但是,当我这样键入时,它会将数据正确地保存在db中:
var user = await _userManager.GetUserAsync(User);
estate.User = user;
context.Add(estate);
我不知道我在这里做错了什么。我在下面提供我的代码,希望你能给我一些提示/建议
这就是我如何基于IdentityDbContext构建上下文:
public class ReaContext : IdentityDbContext<User>
{
public DbSet<Estate> Estates { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseNpgsql("Server=localhost;Port=5432;Database=rea-dev;User Id=postgres;Password=admin;");
}
public ReaContext(DbContextOptions<ReaContext> options)
: base(options)
{ }
public ReaContext()
: base()
{ }
}
这就是我添加服务的方式:
services.AddDbContext<ReaContext>(options => options.UseNpgsql("Server=localhost;Port=5432;Database=rea-dev;User Id=postgres;Password=admin;"));
services.AddIdentity<User, IdentityRole>().AddEntityFrameworkStores<ReaContext>();
services.AddDbContext(options=>options.UseNpgsql(“服务器=localhost;端口=5432;数据库=rea-dev;用户Id=postgres;密码=admin;”);
services.AddIdentity().AddEntityFrameworkStores();
我还提供流畅的Api迁移:
migrationBuilder.CreateTable(
name: "Estates",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn),
CreationDate = table.Column<DateTime>(nullable: false),
UpdateDate = table.Column<DateTime>(nullable: false),
ExpirationDate = table.Column<DateTime>(nullable: false),
City = table.Column<string>(maxLength: 100, nullable: true),
UserId = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Estates", x => x.Id);
table.ForeignKey(
name: "FK_Estates_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateTable(
name: "AspNetUsers",
columns: table => new
{
Id = table.Column<string>(nullable: false),
UserName = table.Column<string>(maxLength: 256, nullable: true),
NormalizedUserName = table.Column<string>(maxLength: 256, nullable: true),
Email = table.Column<string>(maxLength: 256, nullable: true),
NormalizedEmail = table.Column<string>(maxLength: 256, nullable: true),
EmailConfirmed = table.Column<bool>(nullable: false),
PasswordHash = table.Column<string>(nullable: true),
SecurityStamp = table.Column<string>(nullable: true),
ConcurrencyStamp = table.Column<string>(nullable: true),
PhoneNumber = table.Column<string>(nullable: true),
PhoneNumberConfirmed = table.Column<bool>(nullable: false),
TwoFactorEnabled = table.Column<bool>(nullable: false),
LockoutEnd = table.Column<DateTimeOffset>(nullable: true),
LockoutEnabled = table.Column<bool>(nullable: false),
AccessFailedCount = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUsers", x => x.Id);
});
migrationBuilder.CreateTable(
名称:“不动产”,
列:表=>new
{
Id=table.Column(可空:false)
.Annotation(“Npgsql:ValueGenerationStrategy”,NpgsqlValueGenerationStrategy.SerialColumn),
CreationDate=表.列(可空:false),
UpdateDate=table.Column(可空:false),
ExpirationDate=table.Column(可空:false),
City=table.Column(最大长度:100,可为空:true),
UserId=table.Column(可空:true)
},
约束:表=>
{
表.PrimaryKey(“PK_地产”,x=>x.Id);
表1.外键(
名称:“FK_Estates_AspNetUsers_UserId”,
列:x=>x.UserId,
原则性:“AspNetUsers”,
主栏:“Id”,
onDelete:referentialiction.Restrict);
});
migrationBuilder.CreateTable(
名称:“AspNetUsers”,
列:表=>new
{
Id=table.Column(可空:false),
UserName=table.Column(最大长度:256,可为空:true),
NormalizedUserName=table.Column(maxLength:256,null:true),
Email=table.Column(最大长度:256,可为空:true),
NormalizedEmail=table.Column(maxLength:256,nullable:true),
emailconfirm=table.Column(可空:false),
PasswordHash=table.Column(可空:true),
SecurityStamp=table.Column(可空:true),
ConcurrencyStamp=table.Column(可空:true),
PhoneNumber=table.Column(可空:true),
PhoneNumberConfiged=table.Column(可空:false),
TwoFactorEnabled=table.Column(可空:false),
LockoutEnd=table.Column(可空:true),
LockoutEnabled=table.Column(可空:false),
AccessFailedCount=table.Column(可空:false)
},
约束:表=>
{
表.PrimaryKey(“PK_AspNetUsers”,x=>x.Id);
});
获取模型相关数据的方法多种多样
即时加载:表示从数据库加载相关数据作为初始查询的一部分
显式加载:表示以后从数据库显式加载相关数据
延迟加载:表示在访问导航属性时,相关数据从数据库透明加载
因此,在您的情况下,您可以通过执行以下操作来使用快速加载
:
context.Estates.Include(e => e.User).FirstOrDefault(m => m.Id == id);
var user = await _userManager.Users
.Include(u => u.Estates)
.FirstOrDefaultAsync(YOUR_CONDITION);
有关更多信息,请阅读以下内容:
编辑:在IdentityUser
上实现快速加载模式的示例:
您可以通过以下方式实现此目的:
注入UserManager\u UserManager
在服务/存储库设计模式中创建自己的服务
假设你选择了第一个选项。然后您可以执行以下操作:
context.Estates.Include(e => e.User).FirstOrDefault(m => m.Id == id);
var user = await _userManager.Users
.Include(u => u.Estates)
.FirstOrDefaultAsync(YOUR_CONDITION);
获取模型的相关数据有不同的方法
即时加载:表示从数据库加载相关数据作为初始查询的一部分
显式加载:表示以后从数据库显式加载相关数据
延迟加载:表示在访问导航属性时,相关数据从数据库透明加载
因此,在您的情况下,您可以通过执行以下操作来使用快速加载
:
context.Estates.Include(e => e.User).FirstOrDefault(m => m.Id == id);
var user = await _userManager.Users
.Include(u => u.Estates)
.FirstOrDefaultAsync(YOUR_CONDITION);
有关更多信息,请阅读以下内容:
编辑:在IdentityUser
上实现快速加载模式的示例:
您可以通过以下方式实现此目的:
注入UserManager\u UserManager
在服务/存储库设计模式中创建自己的服务
假设你选择了第一个选项。然后您可以执行以下操作:
context.Estates.Include(e => e.User).FirstOrDefault(m => m.Id == id);
var user = await _userManager.Users
.Include(u => u.Estates)
.FirstOrDefaultAsync(YOUR_CONDITION);
谢谢,我找到了一个用于延迟加载的应用程序,我添加了Microsoft.EntityFrameworkCore.Proxies
包,并如文档所述将我的关系更改为虚拟。现在它工作得很好。非常感谢,因为我不知道加载类型,所以我被困在这几个小时里。出于好奇,有没有办法通过快速加载访问user.estate
?我找到了一些示例,但都是在context对象上,用户没有include
方法。它适用于延迟加载。我认为是的,你可以。通过注入UserManager\u UserManager
,您可以以答案中所示的类似方式使用它。我将用一个例子更新答案。我的意思是针对单用户对象,比如在var user=await\u userManager.GetUserAsync(user);user.Estates.DoStuff()代码>,但如果没有