我正在尝试迁移一个简单的表,但是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 }
);
}
}
我不明白为什么创建 CategoryName 和 CategoryCashFlowId 列
请帮助
答案 0 :(得分:1)
为什么要创建CategoryName和CategoryCashFlowId列
使用这一行:modelBuilder.Entity<Category>().HasKey(c => new { c.Name, c.CashFlowId });
您正在为表Category
创建一个组合键,该键不能是int
。
在您的Transaction
对象中,您正试图为CategoryId
映射键Category
,如之前所述,您的复合键不能成为int
的单个属性,因为组成的性质。因此,此时CategoryId
不是外键,它只是另一个属性。
EF核心将用于Category
对象的主复合键的两个属性放到Transaction
对象中,用作外来复合键。
您可以通过删除组成来解决此问题。
答案 1 :(得分:0)
我认为这是因为您的Transaction
模型具有Category
到CategoryId
模型的引用(导航属性)。但是它实际上不能由Category
引用CategoryId
模型,因为Category
模型实际上具有Name
和CashFlowId
的复合键。因此,Entity Framework将这些添加到幕后以供参考。
我认为您可以使用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
答案 2 :(得分: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
。
答案 3 :(得分:0)
当您将此配置用于...
modelBuilder.Entity<Category>().HasKey(c => new { c.Name, c.CashFlowId });
类别表的主键是Name和CashFlowId,并且用于关联的交易表必须生成这些列。