明確的值設定為產生的屬性Setting Explicit Values for Generated Properties

產生的屬性是的屬性 (可由 EF 或資料庫),其值會產生當實體已加入及/或更新。A generated property is a property whose value is generated (either by EF or the database) when the entity is added and/or updated. 請參閱產生屬性如需詳細資訊。See Generated Properties for more information.

可能會有您要設定產生的屬性,而不需要產生的外顯值的情況。There may be situations where you want to set an explicit value for a generated property, rather than having one generated.

提示

您可以檢視這篇文章範例GitHub 上。You can view this article's sample on GitHub.

模型The model

在本文中使用的模型包含單一Employee實體。The model used in this article contains a single Employee entity.

public class Employee
{
    public int EmployeeId { get; set; }
    public string Name { get; set; }
    public DateTime EmploymentStarted { get; set; }
    public int Salary { get; set; }
    public DateTime? LastPayRaise { get; set; }
}

儲存期間新增明確的值Saving an explicit value during add

Employee.EmploymentStarted屬性已設定為具有新的實體 (使用預設值) 的資料庫所產生的值。The Employee.EmploymentStarted property is configured to have values generated by the database for new entities (using a default value).

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

下列程式碼會插入資料庫中的兩個員工。The following code inserts two employees into the database.

  • 第一個,指定任何值給Employee.EmploymentStarted屬性,以便維持設定為的 CLR 預設值DateTimeFor the first, no value is assigned to Employee.EmploymentStarted property, so it remains set to the CLR default value for DateTime.
  • 秒,我們已設定的明確值1-Jan-2000For the second, we have set an explicit value of 1-Jan-2000.
using (var context = new EmployeeContext())
{
    context.Employees.Add(new Employee { Name = "John Doe" });
    context.Employees.Add(new Employee { Name = "Jane Doe", EmploymentStarted = new DateTime(2000, 1, 1) });
    context.SaveChanges();

    foreach (var employee in context.Employees)
    {
        Console.WriteLine(employee.EmployeeId + ": " + employee.Name + ", " + employee.EmploymentStarted);
    }
}

輸出顯示資料庫產生值的第一位員工,並使用第二個我們明確的值。Output shows that the database generated a value for the first employee and our explicit value was used for the second.

1: John Doe, 1/26/2017 12:00:00 AM
2: Jane Doe, 1/1/2000 12:00:00 AM

明確值插入 SQL Server IDENTITY 資料行Explicit values into SQL Server IDENTITY columns

依照慣例Employee.EmployeeId屬性是存放區產生IDENTITY資料行。By convention the Employee.EmployeeId property is a store generated IDENTITY column.

大部分的情況下,如上所示的方法可用於索引鍵屬性。For most situations, the approach shown above will work for key properties. 不過,將明確值插入 SQL ServerIDENTITY資料行中,您必須手動啟用IDENTITY_INSERT之前先呼叫SaveChanges()However, to insert explicit values into a SQL Server IDENTITY column, you need to manually enable IDENTITY_INSERT before calling SaveChanges().

注意

我們有功能要求在我們的待辦項目,SQL Server 提供者內自動執行此動作。We have a feature request on our backlog to do this automatically within the SQL Server provider.

using (var context = new EmployeeContext())
{
    context.Employees.Add(new Employee { EmployeeId = 100, Name = "John Doe" });
    context.Employees.Add(new Employee { EmployeeId = 101, Name = "Jane Doe" });

    context.Database.OpenConnection();
    try
    {
        context.Database.ExecuteSqlCommand("SET IDENTITY_INSERT dbo.Employees ON");
        context.SaveChanges();
        context.Database.ExecuteSqlCommand("SET IDENTITY_INSERT dbo.Employees OFF");
    }
    finally
    {
        context.Database.CloseConnection();
    }


    foreach (var employee in context.Employees)
    {
        Console.WriteLine(employee.EmployeeId + ": " + employee.Name);
    }
}

輸出會顯示所提供的識別碼已儲存至資料庫。Output shows that the supplied ids were saved to the database.

100: John Doe
101: Jane Doe

更新期間設定明確的值Setting an explicit value during update

Employee.LastPayRaise屬性已設定為具有由資料庫更新時所產生的值。The Employee.LastPayRaise property is configured to have values generated by the database during updates.

modelBuilder.Entity<Employee>()
    .Property(b => b.LastPayRaise)
    .ValueGeneratedOnAddOrUpdate();

modelBuilder.Entity<Employee>()
    .Property(b => b.LastPayRaise)
    .Metadata.AfterSaveBehavior = PropertySaveBehavior.Ignore;

注意

根據預設,EF Core 將會擲回例外狀況,如果您嘗試儲存屬性設定為在更新期間產生的外顯值。By default, EF Core will throw an exception if you try to save an explicit value for a property that is configured to be generated during update. 若要避免這個問題,您需要較低層級的中繼資料 API 下拉式清單,然後設定AfterSaveBehavior(如上所示)。To avoid this, you need to drop down to the lower level metadata API and set the AfterSaveBehavior (as shown above).

注意

在 EF 核心 2.0 中的變更:在舊版本中則包含儲存行為透過控制IsReadOnlyAfterSave旗標。Changes in EF Core 2.0: In previous releases the after-save behavior was controlled through the IsReadOnlyAfterSave flag. 這個旗標已經認定為過時並取代AfterSaveBehaviorThis flag has been obsoleted and replaced by AfterSaveBehavior.

也沒有觸發程序在資料庫中產生的值對LastPayRaise期間的資料行UPDATE作業。There is also a trigger in the database to generate values for the LastPayRaise column during UPDATE operations.

CREATE TRIGGER [dbo].[Employees_UPDATE] ON [dbo].[Employees]
	AFTER UPDATE
AS
BEGIN
	SET NOCOUNT ON;
                  
	IF ((SELECT TRIGGER_NESTLEVEL()) > 1) RETURN;
                  
	IF UPDATE(Salary) AND NOT Update(LastPayRaise)
	BEGIN
		DECLARE @Id INT
		DECLARE @OldSalary INT
		DECLARE @NewSalary INT
          
		SELECT @Id = INSERTED.EmployeeId, @NewSalary = Salary        
		FROM INSERTED
          
		SELECT @OldSalary = Salary        
		FROM deleted
          
		IF @NewSalary > @OldSalary
		BEGIN
			UPDATE dbo.Employees
			SET LastPayRaise = CONVERT(date, GETDATE())
			WHERE EmployeeId = @Id
		END
	END
END

下列程式碼會增加資料庫中的兩個員工的薪資。The following code increases the salary of two employees in the database.

  • 第一個,指定任何值給Employee.LastPayRaise屬性,因此它會維持設定為 null。For the first, no value is assigned to Employee.LastPayRaise property, so it remains set to null.
  • 秒,我們設定一週前 (目付款後引發) 明確的值。For the second, we have set an explicit value of one week ago (back dating the pay raise).
using (var context = new EmployeeContext())
{
    var john = context.Employees.Single(e => e.Name == "John Doe");
    john.Salary = 200;

    var jane = context.Employees.Single(e => e.Name == "Jane Doe");
    jane.Salary = 200;
    jane.LastPayRaise = DateTime.Today.AddDays(-7);

    context.SaveChanges();

    foreach (var employee in context.Employees)
    {
        Console.WriteLine(employee.EmployeeId + ": " + employee.Name + ", " + employee.LastPayRaise);
    }
}

輸出顯示資料庫產生值的第一位員工,並使用第二個我們明確的值。Output shows that the database generated a value for the first employee and our explicit value was used for the second.

1: John Doe, 1/26/2017 12:00:00 AM
2: Jane Doe, 1/19/2017 12:00:00 AM