0

我正在尝试迁移一个简单的表,但 ef-core 正在创建我没有指定的其他列

这是我用来创建 sql 表的模型

public class Transaction
{
        [Key]
        public int Id { get; set; }

        [Required]
        public decimal Amount { get; set; }

        [Required]
        public DateTime DateTimeCreated { get; set; } = DateTime.UtcNow;

        [MaxLength(1024)]
        public string Description { get; set; }

        [Required]
        public int CategoryId { get; set; }

        public virtual Category Category { get; set; }

        [Required]
        public int UserId { get; set; }

        public virtual User User { get; set; }
    }

EF-Core 正在创建下表。

如何阻止 EF-Core 生成 CategoryName 和 CategoryCashFlowId 列

migrationBuilder.CreateTable(
                name: "Transactions",
                columns: table => new
                {
                    Id = table.Column<int>(nullable: false)
                        .Annotation("SqlServer:Identity", "1, 1"),
                    Amount = table.Column<decimal>(nullable: false),
                    DateTimeCreated = table.Column<DateTime>(nullable: false),
                    Description = table.Column<string>(maxLength: 1024, nullable: true),
                    CategoryId = table.Column<int>(nullable: false),
                    CategoryName = table.Column<string>(nullable: false),
                    CategoryCashFlowId = table.Column<int>(nullable: false),
                    UserId = table.Column<int>(nullable: false)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Transactions", x => x.Id);
                    table.ForeignKey(
                        name: "FK_Transactions_Users_UserId",
                        column: x => x.UserId,
                        principalTable: "Users",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Cascade);
                    table.ForeignKey(
                        name: "FK_Transactions_Categories_CategoryName_CategoryCashFlowId",
                        columns: x => new { x.CategoryName, x.CategoryCashFlowId },
                        principalTable: "Categories",
                        principalColumns: new[] { "Name", "CashFlowId" },
                        onDelete: ReferentialAction.Cascade);
                });

这是我流利的api代码

protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            //base.OnModelCreating(modelBuilder);

            modelBuilder.Entity<User>().HasIndex("Username").IsUnique();
            modelBuilder.Entity<Category>().HasKey(c => new { c.Name, c.CashFlowId });

            modelBuilder.Entity<Common.Models.CashFlow>().HasData(
                new CashFlow { Id = 1, Name = "Income" },
                new CashFlow { Id = 2, Name = "Expense" }
            );

            modelBuilder.Entity<Common.Models.Category>().HasData(
                new Category { Id = 1, Name = "Food and Drinks", CashFlowId = 2 },
                new Category { Id = 2, Name = "Travel", CashFlowId = 2 },
                new Category { Id = 3, Name = "Salary", CashFlowId = 1 }
            );
        }

编辑 1:类别模型

public class Category
{
        public int Id { get; set; }

        /// <summary>
        /// <remarks> Is Indexed with CashflowId </remarks>
        /// </summary>
        [MaxLength(32)]
        [Required]
        public string Name { get; set; }

        [Required]
        public int CashFlowId { get; set; }

        public CashFlow CashFlow { get; set; }

}

编辑 2:添加了 CashFlow 模型

public class CashFlow
{
        [Key]
        public int Id { get; set; }

        [MaxLength(32)]
        public string Name { get; set; }
}

编辑 3:发布了我的 DbContext

public class AppDbContext : DbContext
    {

        public DbSet<User> Users { get; set; }

        public DbSet<Common.Models.Transaction> Transactions { get; set; }

        public DbSet<Category> Categories { get; set; }

        public DbSet<CashFlow> CashFlows { get; set; }

        public AppDbContext(DbContextOptions<AppDbContext> dbContextOptions) : base(dbContextOptions)
        {
            ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            //base.OnModelCreating(modelBuilder);

            modelBuilder.Entity<User>().HasIndex("Username").IsUnique();
            modelBuilder.Entity<Category>().HasKey(c => new { c.Name, c.CashFlowId });

            modelBuilder.Entity<Common.Models.CashFlow>().HasData(
                new CashFlow { Id = 1, Name = "Income" },
                new CashFlow { Id = 2, Name = "Expense" }
            );

            modelBuilder.Entity<Common.Models.Category>().HasData(
                new Category { Id = 1, Name = "Food and Drinks", CashFlowId = 2 },
                new Category { Id = 2, Name = "Travel", CashFlowId = 2 },
                new Category { Id = 3, Name = "Salary", CashFlowId = 1 }
            );
        }
    }

我不明白为什么要创建CategoryNameCategoryCashFlowId

请帮忙

4

4 回答 4

1

为什么要创建 CategoryName 和 CategoryCashFlowId 列

使用这一行:modelBuilder.Entity<Category>().HasKey(c => new { c.Name, c.CashFlowId });您正在为Category不能是int.

在您的Transaction对象中,您正尝试CategoryId为您映射一个键,Category如前所述,您的复合键不能int只是组合性质的单一属性。所以此时CategoryId不​​是外键,它只是另一个属性。

EF 核心将您用于对象的主复合键的两个属性放入您的Category对象中,Transaction以用作外部复合键。

您可以通过删除组合来解决此问题。

于 2019-10-19T09:21:38.867 回答
0

类别的现金流应该是虚拟的。

public virtual CashFlow CashFlow { get; set; }

类别应该是

public class Category
{
        [Key]
        public int Id { get; set; }

        /// <summary>
        /// <remarks> Is Indexed with CashflowId </remarks>
        /// </summary>
        [MaxLength(32)]
        [Required]
        public string Name { get; set; }

        [Required]
        [Index("IX_NameCashFlowId", 1, IsUnique = true)]
        public int CashFlowId { get; set; }

        [Index("IX_NameCashFlowId", 1, IsUnique = true)]
        public CashFlow CashFlow { get; set; }

}

modelBuilder.Entity<Category>().HasKey不需要此设置。

于 2019-10-19T09:27:12.470 回答
0

我相信这是因为您的Transaction模型具有模型的引用(导航属性)Category以及CategoryId. 但它实际上不能通过 引用Category模型,CategoryId因为Category模型实际上具有Nameand的复合键CashFlowId。所以实体框架在幕后添加这些来引用它。

Category我认为您可以在使用时创建一个备用键,CategoryId并且可以在不创建额外列的情况下以这种方式引用它。

modelBuilder.Entity<Category>()
    .HasKey(c => new { c.Name, c.CashFlowId })
    .HasAlternateKey(c => c.CategoryId);

参考:https ://docs.microsoft.com/en-us/ef/core/modeling/alternate-keys

于 2019-10-19T09:23:00.197 回答
0

当你使用这个配置

modelBuilder.Entity<Category>().HasKey(c => new { c.Name, c.CashFlowId });

类别表的主键是 Name 和 CashFlowId,关系的事务表必须生成这些列。

于 2019-10-19T09:37:53.230 回答