在 C# 中使用 LINQ to EF(Entity Framework)时,经常会遇到添加记录后获取自增 ID 以及 “ID” 列不是自增列不让插入的问题,下面为你详细介绍这两个问题的解决方案。
1. 添加记录后获取添加的自增 ID
在 Entity Framework 中,当你向数据库中插入一条记录,并且该记录的主键是自增列时,EF 会自动在保存更改后更新实体对象的主键属性。以下是一个示例代码:
using System;
using System.Data.Entity;
using System.Linq;
// 定义实体类
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
}
// 定义数据库上下文类
public class ProductContext : DbContext
{
public DbSet<Product> Products { get; set; }
}
class Program
{
static void Main()
{
using (var context = new ProductContext())
{
// 创建一个新的Product对象
var newProduct = new Product { Name = "New Product" };
// 将新对象添加到上下文中
context.Products.Add(newProduct);
// 保存更改到数据库
context.SaveChanges();
// 获取插入记录的自增ID
int insertedId = newProduct.Id;
Console.WriteLine($"插入记录的自增ID是: {insertedId}");
}
}
}
代码解释:
- 定义实体类:
Product
类表示数据库中的一个表,Id
属性是自增主键。 - 定义数据库上下文类:
ProductContext
继承自DbContext
,并包含一个DbSet<Product>
属性,用于操作Product
表。 - 插入记录:创建一个新的
Product
对象,并将其添加到context.Products
中,然后调用context.SaveChanges()
方法将更改保存到数据库。 - 获取自增 ID:在调用
SaveChanges()
方法后,newProduct.Id
属性会自动更新为插入记录的自增 ID。
2. 叫 “ID” 的列不是自增列不让插入的问题
当 “ID” 列不是自增列时,EF 默认会将其视为主键,并且在插入记录时要求你手动指定该列的值。如果你不想手动指定,可以通过数据注解或 Fluent API 来配置该列不是主键。
使用数据注解
using System.ComponentModel.DataAnnotations;
// 定义实体类
public class Order
{
[Key]
public string OrderNumber { get; set; } // 手动指定主键
public int ID { get; set; } // 不是主键
public string CustomerName { get; set; }
}
// 定义数据库上下文类
public class OrderContext : DbContext
{
public DbSet<Order> Orders { get; set; }
}
class Program2
{
static void Main()
{
using (var context = new OrderContext())
{
var newOrder = new Order
{
OrderNumber = "ORD001",
CustomerName = "John Doe"
};
context.Orders.Add(newOrder);
context.SaveChanges();
}
}
}
使用 Fluent API
using System.Data.Entity;
using System.Data.Entity.Infrastructure.Annotations;
using System.ComponentModel.DataAnnotations.Schema;
// 定义实体类
public class Invoice
{
public int ID { get; set; }
public string InvoiceNumber { get; set; }
}
// 定义数据库上下文类
public class InvoiceContext : DbContext
{
public DbSet<Invoice> Invoices { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Invoice>()
.HasKey(i => i.InvoiceNumber); // 手动指定主键
modelBuilder.Entity<Invoice>()
.Property(i => i.ID)
.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute())); // 如果需要,可以添加索引
}
}
class Program3
{
static void Main()
{
using (var context = new InvoiceContext())
{
var newInvoice = new Invoice
{
InvoiceNumber = "INV001"
};
context.Invoices.Add(newInvoice);
context.SaveChanges();
}
}
}
代码解释:
- 数据注解:使用
[Key]
特性手动指定主键,这样 “ID” 列就不会被视为主键,可以正常插入记录。 - Fluent API:在
OnModelCreating
方法中使用HasKey
方法手动指定主键,同样可以解决 “ID” 列不是自增列不让插入的问题。
总结
在使用 Entity Framework(EF)时,“ID” 列不是自增列就不能插入记录这种情况,主要和 EF 的默认行为、主键约束相关,下面为你详细解释:
EF 默认将 “ID” 列视为主键
EF 有一套约定规则,当实体类中存在名为 “ID” 或者 “类名 + ID”(例如
ProductID
对于 Product
类)的属性时,EF 会默认将其视为主键。主键在数据库中有着特殊的约束要求:- 唯一性:主键的值在整个表中必须是唯一的,不能有重复值。
- 非空性:主键列的值不能为
NULL
。
插入记录时的主键处理机制
当你向数据库插入一条记录时,EF 会根据主键的配置来处理插入操作:
- 自增主键:如果 “ID” 列被设置为自增列(例如在 SQL Server 中的
IDENTITY
属性、MySQL 中的AUTO_INCREMENT
属性),数据库会自动为插入的新记录生成一个唯一的自增 ID 值。在这种情况下,你在代码中不需要为 “ID” 属性赋值,EF 会忽略该属性的插入值,而由数据库自动处理。 - 非自增主键:如果 “ID” 列不是自增列,EF 会期望你在代码中为 “ID” 属性提供一个有效的、唯一的非空值。如果你没有手动为其赋值,EF 在执行插入操作时会因为主键值为空或者不唯一而抛出异常,从而导致插入失败。