在 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}");
        }
    }
}

 

代码解释:

  1. 定义实体类Product类表示数据库中的一个表,Id属性是自增主键。
  2. 定义数据库上下文类ProductContext继承自DbContext,并包含一个DbSet<Product>属性,用于操作Product表。
  3. 插入记录:创建一个新的Product对象,并将其添加到context.Products中,然后调用context.SaveChanges()方法将更改保存到数据库。
  4. 获取自增 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 在执行插入操作时会因为主键值为空或者不唯一而抛出异常,从而导致插入失败。