繁体   English   中英

为什么Entity Id的AutoIncrement异常变化,如何重置? - ASP.NET 核心,EF 核心

[英]Why has AutoIncrement of Entity Id changed abnormally, and how to reset it? - ASP.NET Core, EF Core

当新值被添加到我的数据库的User表中时,实体 ID 应该自动编号,比之前添加的实体多一个。 这最初工作正常,但是,现在添加到此表的任何新实体的UserId为 1014,而最后一个工作实体的UserId为 12。

我没有更改将新值添加到表中的代码,对表所做的唯一更改是手动更改某些实体的字段UserPass的值。

我想知道是否可以解释为什么会出现此自动递增问题,我的第二个问题是是否有任何解决方法,例如重置User表的自动递增值。

我的程序在 ASP.NET 6.0 Core Web App 上,我正在使用 Entity Framework Core 来管理数据库中的表。

我是一名对 ASP.NET Core 和 EF Core 以及如何解决这个问题有基本了解的学生,因此非常感谢您提供尽可能多的简化解释。

这是我的User.cs model 的代码:

namespace AQA_A_Level_CS_NEA__Suvat_Solver_.Models
{
    public class User
    {
        public int UserId { get; set; }
        public string UserName { get; set; } = string.Empty;
        public string UserPass { get; set; } = string.Empty;
        public int UserCorrectAnsw { get; set; } = 0;
        public int UserTotalAnsw { get; set; } = 0;

        public List<UsertoCourses> UsertoCourses { get; set; }


    }
}

这是从User.cs model 迁移的代码:

using Microsoft.EntityFrameworkCore.Migrations;

#nullable disable

namespace AQA_A_Level_CS_NEA__Suvat_Solver_.Migrations
{
    public partial class UserCourseRelation : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.CreateTable(
                name: "UsertoCourses",
                columns: table => new
                {
                    UserId = table.Column<int>(type: "int", nullable: false),
                    CourseId = table.Column<int>(type: "int", nullable: false)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_UsertoCourses", x => new { x.UserId, x.CourseId });
                    table.ForeignKey(
                        name: "FK_UsertoCourses_Courses_CourseId",
                        column: x => x.CourseId,
                        principalTable: "Courses",
                        principalColumn: "CourseId",
                        onDelete: ReferentialAction.Cascade);
                    table.ForeignKey(
                        name: "FK_UsertoCourses_User_UserId",
                        column: x => x.UserId,
                        principalTable: "User",
                        principalColumn: "UserId",
                        onDelete: ReferentialAction.Cascade);
                });

            migrationBuilder.CreateIndex(
                name: "IX_UsertoCourses_CourseId",
                table: "UsertoCourses",
                column: "CourseId");
        }

        protected override void Down(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.DropTable(
                name: "UsertoCourses");
        }
    }
}

这是我的ApplicationDbContext.cs代码:

namespace AQA_A_Level_CS_NEA__Suvat_Solver_.Data
{
    using Microsoft.EntityFrameworkCore;
    using AQA_A_Level_CS_NEA__Suvat_Solver_.Models;
    public class ApplicationDbContext : DbContext
    {

        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options)
        {

        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Question>()
            .HasKey(c => c.QuestId);
            modelBuilder.Entity<UsertoCourses>()
            .HasKey(c => new { c.UserId, c.CourseId });
            modelBuilder.Entity<QuestiontoCourses>()
            .HasKey(c => new { c.QuestId, c.CourseId });
        }

        public DbSet<User> User { get; set; }
        public DbSet<Course> Courses { get; set; }
        public DbSet<Question> Question { get; set; }
        public DbSet<UsertoCourses> UsertoCourses { get; set; }
        public DbSet<QuestiontoCourses> QuestiontoCourses { get; set; }
    }
}

非常感谢。

这通常发生在通过某种方式添加了许多行然后又将其删除的情况下。 删除行,即使删除表的“尾部”也不会重置自动递增序列。 如果您正在执行维护事件并希望将种子返回到特定点,通常可以重新播种序列,例如 SQL 服务器的标识。 (即,如果您有要回滚的数据导入,请删除这些记录并恢复种子)

对于 SQL 服务器,这是:

DBCC CHECKIDENT ('User', REESEED, 13)

恢复在 13、14 等位置插入 ID

一般来说,对于无意义的 PK,Identity 值应该无关紧要,只是它是唯一的和索引的。 使用标识列可提供最佳性能,但它们是可以猜测的,因此如果您以任何方式以用户可以看到或可能操纵它们的方式公开这些 PK,则需要考虑到这一点。 例如,在 web 请求的 URL 上,或将 ID 作为表单数据的一部分传递。 UserId 12 可以在 POST 中替换为 UserId 11。

有意义的键不应使用标识列。 这些通常是业务逻辑所依赖的东西,并且可能与代码库中的枚举之类的东西相关联,并用于条件逻辑。

关于 GUID 的想法:

对于可以通过表单数据检查和提交的值,以及您想更好地检测和阻止篡改的地方,GUID 是一个不错的选择,但我会严格避免将它们用作 PK 和 FK,因为 GUID 可能会在索引中造成碎片,特别是聚簇索引。 顺序 GUID 可以帮助缓解这种情况,但在某种程度上会破坏允许不可猜测值的目的。 证明顺序 GUID PK 合理的是分布式数据库系统,其中记录可以插入多个数据库副本之一并复制到其他副本。

相反,将所有 PK 和 FK 关系保留为标识列,并将 append 保留为索引(非集群)GUID 列以用作可搜索的“键”。 这些键是您可以在 URL 或表单数据中发送并用于定位实际 PK 的内容,同时仍然保持聚簇索引的性能优势,以便通过 FK 将相关数据读取到 PK。

即不是 GET /Users/12 解析为:

return _context.Users.Single(x => x.UserId == userId)
    .ProjectTo<UserViewModel>(config);

GET /Users/c3b03d9d-cf57-4dca-a060-6a2ea827d672(例如 GUID,例如破折号语法,通常使用无破折号)

return _context.Users.Single(x => x.UserKey == userKey);
    .ProjectTo<UserViewModel>(config);

用户仍然有一个 UserId PK 为 12,这是每个其他实体引用该用户的 FK,但也有一个 UserKey GUID,它将是该用户的显示密钥。 发送到 UI 的视图模型永远不会显示 PK 或 FK,只会显示键。 通过这种方式,PK 仍然真正没有意义并受到保护。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM