显式设置生成值属性的值

    在某些环境下你可能想要显式设置生成值属性的值,而不是使用生成的值。

    本文使用的模型只包含一个 实体。‘

    新实体的 Employee.EmployentStarted 属性被配置为由数据库生成值(使用默认值)。

    1. modelBuilder.Entity<Employee>()
    2. .Property(b => b.EmploymentStarted)
    3. .HasDefaultValueSql("CONVERT(date, GETDATE())");

    以下代码会将两条 employee 数据插入到数据库中。

    • 对于第一条数据,不会为 Employee.EmploymentStarted 属性赋值,所以其依然会被设置为 DateTime 类型的运行时默认值。
    • 对于第二条数据,我们显式将其值设置为 1-Jan-2000
    1. using (var context = new EmployeeContext())
    2. {
    3. context.Employees.Add(new Employee { Name = "John Doe" });
    4. context.Employees.Add(new Employee { Name = "Jane Doe", EmploymentStarted = new DateTime(2000, 1, 1) });
    5. context.SaveChanges();
    6. foreach (var employee in context.Employees)
    7. {
    8. Console.WriteLine(employee.EmployeeId + ": " + employee.Name + ", " + employee.EmploymentStarted);
    9. }
    10. }

    按照惯例,Employee.EmployeeId 属性是数据库生成的 IDENTITY 列。

    大多情况下,上述方法对键属性有效。然而,想要为 SQL Server IDENTITY 列显式指定值的话,你需要在调用 SaveChanges() 前手动启用 IDENTITY_INSERT

    1. using (var context = new EmployeeContext())
    2. {
    3. context.Employees.Add(new Employee { EmployeeId = 100, Name = "John Doe" });
    4. context.Employees.Add(new Employee { EmployeeId = 101, Name = "Jane Doe" });
    5. context.Database.OpenConnection();
    6. try
    7. {
    8. context.Database.ExecuteSqlCommand("SET IDENTITY_INSERT dbo.Employees ON");
    9. context.Database.ExecuteSqlCommand("SET IDENTITY_INSERT dbo.Employees OFF");
    10. }
    11. finally
    12. {
    13. context.Database.CloseConnection();
    14. }
    15. foreach (var employee in context.Employees)
    16. {
    17. Console.WriteLine(employee.EmployeeId + ": " + employee.Name);
    18. }
    19. }

    输出显式为已提供并保存到数据库的 id 值。

    1. 100: John Doe
    2. 101: Jane Doe

    Employee.LastPayRaise 属性被配置为在更新时由数据库生成值。

    还需要一个数据库触发器来在 UPDATE 操作期间为 LastPayRaise 列生成值。

    1. CREATE TRIGGER [dbo].[Employees_UPDATE] ON [dbo].[Employees]
    2. AFTER UPDATE
    3. AS
    4. BEGIN
    5. SET NOCOUNT ON;
    6. IF ((SELECT TRIGGER_NESTLEVEL()) > 1) RETURN;
    7. IF UPDATE(Salary) AND NOT Update(LastPayRaise)
    8. BEGIN
    9. DECLARE @Id INT
    10. DECLARE @NewSalary INT
    11. FROM INSERTED
    12. SELECT @OldSalary = Salary
    13. FROM deleted
    14. IF @NewSalary > @OldSalary
    15. BEGIN
    16. UPDATE dbo.Employees
    17. SET LastPayRaise = CONVERT(date, GETDATE())
    18. WHERE EmployeeId = @Id
    19. END
    20. END
    21. END

    以下代码会在数据库中对两个 employee 的 salary 进行递增。

    • 对于第一个 employee,没有为 Employee.LastPayRaise 赋值,所以其依然会被设为 null。
    • 对于第二个 employee,我们显式将其属性值设置为一周前。
    1. using (var context = new EmployeeContext())
    2. {
    3. var john = context.Employees.Single(e => e.Name == "John Doe");
    4. john.Salary = 200;
    5. var jane = context.Employees.Single(e => e.Name == "Jane Doe");
    6. jane.Salary = 200;
    7. jane.LastPayRaise = DateTime.Today.AddDays(-7);
    8. context.SaveChanges();
    9. foreach (var employee in context.Employees)
    10. {
    11. Console.WriteLine(employee.EmployeeId + ": " + employee.Name + ", " + employee.LastPayRaise);

    输出显式为数据库为第一个 employee 生成的属性值和我们为第二个 employee 显式设置的值。