给出以下两个类:
public class PortalUser : IdentityUser
{
public Guid? RefreshTokenId { get; set; }
public RefreshToken RefreshToken { get; set; }
}
public class RefreshToken
{
public Guid Id { get; set; }
public string Token { get; set; }
public string UserId { get; set; }
public PortalUser User { get; set; }
public RefreshToken(string token, string userId)
{
Token = token;
UserId = userId;
}
}
我建立了一对一的关系-用户可以只有一个刷新令牌,或者根本没有。请参阅下面的配置。
public void Configure(EntityTypeBuilder<PortalUser> builder)
{
builder.HasOne(x => x.RefreshToken).WithOne(x => x.User)
.HasForeignKey<PortalUser>(x => x.RefreshTokenId).OnDelete(DeleteBehavior.SetNull);
}
public class RefreshTokenConfiguration : IEntityTypeConfiguration<RefreshToken>
{
public void Configure(EntityTypeBuilder<RefreshToken> builder)
{
builder.ToTable("AspNetUserRefreshTokens");
builder.HasKey(x => x.Id);
builder.Property(x => x.Id).ValueGeneratedOnAdd();
builder.Property(x => x.Token).IsRequired();
builder.HasOne(x => x.User).WithOne(x => x.RefreshToken)
.HasForeignKey<RefreshToken>(x => x.UserId).OnDelete(DeleteBehavior.Cascade);
}
}
现在,当删除用户时,级联删除效果很好-刷新令牌也被删除,但是当我删除单个刷新令牌时,PortalUser中的FK仍为SET。
这对我来说似乎不对,知道我在做什么错吗?
答案 0 :(得分:1)
我试图重现您的问题,据我所知您的配置正确。
您可能会错过的一件事(或只是未包括在问题中)是如何将EntityTypeBuilder<PortalUser>
连接到数据库上下文中。我成功完成了以下配置:
public class DbContext: IdentityDbContext<PortalUser>
{
public DbSet<RefreshToken> AspNetUserRefreshTokens { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder builder)
{
builder.UseSqlServer("needs a connection string");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.ApplyConfiguration(new RefreshTokenConfiguration());
modelBuilder.ApplyConfiguration(new PortalUserConfiguration()); // i suspect this piece can be your issue, check if you've got it hooked up
}
public class PortalUserConfiguration : IEntityTypeConfiguration<PortalUser>
{
public void Configure(EntityTypeBuilder<PortalUser> builder)
{
builder.HasOne(x => x.RefreshToken)
.WithOne(x => x.User)
.HasForeignKey<PortalUser>(x => x.RefreshTokenId)
.OnDelete(DeleteBehavior.SetNull);
}
}
public class RefreshTokenConfiguration : IEntityTypeConfiguration<RefreshToken>
{
public void Configure(EntityTypeBuilder<RefreshToken> builder)
{
builder.ToTable("AspNetUserRefreshTokens");
builder.HasKey(x => x.Id);
builder.Property(x => x.Id).ValueGeneratedOnAdd();
builder.Property(x => x.Token).IsRequired();
builder.HasOne(x => x.User).WithOne(x => x.RefreshToken)
.HasForeignKey<RefreshToken>(x => x.UserId).OnDelete(DeleteBehavior.Cascade);
}
}
}
我的测试台看起来像这样:
class Program
{
static void Main(string[] args)
{
var ctx = new DbContext();
//ctx.Database.EnsureCreated(); // you probably don't need this step
var user = new PortalUser();
var t = new RefreshToken("test", user.Id);
user.RefreshToken = t;
ctx.Users.Add(user);
ctx.SaveChanges();
var token = ctx.AspNetUserRefreshTokens.Find(t.Id);
ctx.Entry(token).State = EntityState.Deleted;
ctx.SaveChanges();
var u = ctx.Users.Find(user.Id);
Console.Write($"RefreshTokenId {u.RefreshTokenId}");
Console.ReadKey();
}
}