產生的值

資料庫資料行可以透過各種方式產生其值:主鍵資料行經常是自動遞增整數、其他資料行具有預設或計算值等等。此頁面詳細說明使用 EF Core 產生組態值的各種模式。

預設值

在關係資料庫上,可以使用預設值來設定資料行;如果插入資料列時沒有該資料行的值,則會使用預設值。

您可以在屬性上設定預設值:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .Property(b => b.Rating)
        .HasDefaultValue(3);
}

您也可以指定用來計算預設值的 SQL 片段:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .Property(b => b.Created)
        .HasDefaultValueSql("getdate()");
}

計算資料行

在大部分關係資料庫上,資料行可以設定為在資料庫中計算其值,通常是參考其他資料行的運算式:

modelBuilder.Entity<Person>()
    .Property(p => p.DisplayName)
    .HasComputedColumnSql("[LastName] + ', ' + [FirstName]");

上述會 建立虛擬 計算資料行,其值會在每次從資料庫擷取時計算。 您也可以指定儲存計算資料行 (有時稱為 持續性 ),這表示它會在資料列的每個更新上計算,並且會與一般資料行一起儲存在磁片上:

modelBuilder.Entity<Person>()
    .Property(p => p.NameLength)
    .HasComputedColumnSql("LEN([LastName]) + LEN([FirstName])", stored: true);

主索引鍵

根據慣例,如果應用程式未提供值,則類型為 short、int、long 或 Guid 的非複合主鍵會設定為為插入實體產生值。 您的資料庫提供者通常會負責必要的設定;例如,SQL Server 中的數值主鍵會自動設定為 IDENTITY 資料行。

如需詳細資訊, 請參閱有關特定繼承對應策略 之金鑰 和 指引的檔。

明確設定值產生

我們上面看到 EF Core 會自動為主鍵設定值產生 ,但我們可能會想要對非索引鍵屬性執行相同的動作。 您可以設定任何屬性,使其針對插入的實體產生其值,如下所示:

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }

    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public DateTime Inserted { get; set; }
}

同樣地,屬性可以設定為在新增或更新時產生其值:

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }

    [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
    public DateTime LastUpdated { get; set; }
}

不同于預設值或計算資料行,我們不會指定 如何產生值;這取決於所使用的資料庫提供者。 資料庫提供者可能會自動設定某些屬性類型的值產生,但其他提供者可能會要求您手動設定如何產生值。

例如,在 SQL Server 上,當 GUID 屬性設定為主鍵時,提供者會自動使用演算法產生最佳的循序 GUID 值來執行產生用戶端的值。 不過,在 ValueGeneratedOnAdd DateTime 屬性上指定 將不會有任何作用( 請參閱下面的章節以取得 DateTime 值產生 )。

同樣地,在新增或更新時設定為產生的 byte[] 屬性,並以 rowversion 資料類型設定為並行權杖,以便在資料庫中自動產生值。 不過,指定 ValueGeneratedOnAdd 沒有任何作用。

如需支援的特定值產生技術,請參閱提供者的檔。 您可以在這裡 找到 SQL Server 值產生檔。

產生日期/時間值

常見的要求是具有資料庫資料行,其中包含第一次插入資料列的日期/時間(新增時產生的值),或上次更新時(新增或更新時產生的值)。 由於有各種策略可以這麼做,EF Core 提供者通常不會針對日期/時間資料行自動設定值產生 - 您必須自行設定。

建立時間戳記

將日期/時間資料行設定為具有資料列的建立時間戳記,通常是使用適當的 SQL 函式設定預設值。 例如,在 SQL Server 上,您可以使用下列專案:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .Property(b => b.Created)
        .HasDefaultValueSql("getdate()");
}

請務必選取適當的函式,因為可能有數個函式存在(例如 GETDATE()GETUTCDATE() )。

更新時間戳記

雖然預存計算資料行似乎是管理上次更新時間戳記的好解決方案,但資料庫通常不允許在計算資料行中指定這類 GETDATE() 函式。 或者,您可以設定資料庫觸發程式以達到相同的效果:

CREATE TRIGGER [dbo].[Blogs_UPDATE] ON [dbo].[Blogs]
    AFTER UPDATE
AS
BEGIN
    SET NOCOUNT ON;

    IF ((SELECT TRIGGER_NESTLEVEL()) > 1) RETURN;

    UPDATE B
    SET LastUpdated = GETDATE()
    FROM dbo.Blogs AS B
    INNER JOIN INSERTED AS I
        ON B.BlogId = I.BlogId
END

如需建立觸發程式的詳細資訊, 請參閱在移 轉中使用原始 SQL 的檔。

覆寫值產生

雖然屬性已設定為產生值,但在許多情況下,您仍可能會明確指定其值。 這是否實際運作取決於已設定的特定值產生機制:雖然您可以指定明確的值,而不是使用資料行的預設值,但計算資料行無法執行相同的作業。

若要使用明確值覆寫產生值,只要將 屬性設定為不是該屬性類型之 CLR 預設值的任何值( null 針對 string0intGuid.EmptyGuid 等)。

注意

嘗試將明確值插入 SQL Server IDENTITY 預設會失敗; 如需因應措施 ,請參閱這些檔。

若要為已設定為新增或更新時產生的值的屬性提供明確值,您也必須設定 屬性,如下所示:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>().Property(b => b.LastUpdated)
        .ValueGeneratedOnAddOrUpdate()
        .Metadata.SetAfterSaveBehavior(PropertySaveBehavior.Save);
}

無值產生

除了上述案例等特定案例之外,屬性通常未設定任何值產生;這表示應用程式必須一律提供要儲存至資料庫的值。 此值必須先指派給新實體,才能新增至內容。

不過,在某些情況下,您可能想要停用慣例所設定的值產生。 例如,int 類型的主鍵通常會隱含地設定為 value-generated-on-add(例如 SQL Server 上的識別資料行)。 您可以透過下列方式停用此專案:

public class Blog
{
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int BlogId { get; set; }

    public string Url { get; set; }
}