實體屬性
模型中的每個實體類型都有一組屬性,EF Core 會從資料庫讀取和寫入這些屬性。 如果您使用關係資料庫,實體屬性會對應至資料表欄位。
包含和排除的屬性
藉由 慣例,所有具有 getter 和 setter 的公用屬性都會包含在模型中。
您可以排除特定屬性,如下所示:
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
[NotMapped]
public DateTime LoadedFromDatabase { get; set; }
}
欄位名稱
依照慣例,使用關係資料庫時,實體屬性會對應至名稱與 屬性相同的數據表數據行。
如果您要以不同的名稱設定資料列,可以執行下列代碼段:
public class Blog
{
[Column("blog_id")]
public int BlogId { get; set; }
public string Url { get; set; }
}
欄位數據類型
使用關係資料庫時,資料庫提供者會根據 屬性的 .NET 類型選取數據類型。 它也會考慮其他元數據,例如已配置的 最大長度,屬性是否為主鍵的一部分等等。
例如,SQL Server 提供者會將 DateTime
屬性對應至 datetime2(7)
數據行,並將 string
屬性對應至 nvarchar(max)
數據行(或者對應至作為鍵的屬性 nvarchar(450)
)。
您也可以設定資料行來指定某個資料行的確切數據類型。 例如,下列程式碼會將 Url
設定為長度上限為 200
的非 Unicode 字串,並將 Rating
設定為精度為 5
且尺度為 2
的十進位數:
public class Blog
{
public int BlogId { get; set; }
[Column(TypeName = "varchar(200)")]
public string Url { get; set; }
[Column(TypeName = "decimal(5, 2)")]
public decimal Rating { get; set; }
}
最大長度
設定最大長度會為資料庫提供者提供有關指定屬性選擇之適當數據行數據類型的提示。 長度上限僅適用於陣列資料類型,例如 string
和 byte[]
。
備註
Entity Framework 不會在將數據傳遞至提供者之前,對長度上限進行任何驗證。 提供者或數據存放區負責驗證是否適當。 例如,當以 SQL Server 為目標時,超過最大長度會導致例外狀況,因為基礎數據行的數據類型不允許儲存多餘的數據。
在下列範例中,設定長度上限為 500 會導致在 SQL Server 上建立類型 nvarchar(500)
的數據行:
public class Blog
{
public int BlogId { get; set; }
[MaxLength(500)]
public string Url { get; set; }
}
精度與範圍
某些關係型資料類型支援精確度和小數位的屬性;這些屬性控制可儲存的數值以及資料行所需的存儲空間。 哪些資料類型支持精確度和小數位數取決於資料庫,但在大多數資料庫中,decimal
和 DateTime
類型都支持這些屬性。 針對 decimal
屬性,精度定義數據欄位中表達任何值所需的最大位數,而小數位數則定義最大的小數位數。 針對 DateTime
屬性,精確度是指表示秒的小數部分所需的最大位數,不使用比例。
注意
Entity Framework 不會在將數據傳遞至提供者之前,對精度或小數刻度進行任何驗證。 是否驗證取決於提供者或數據存放區的決定。 例如,當以 SQL Server 為目標時,資料類型為 datetime
的列不允許設定精確度,而 datetime2
的列可以將精確度設定在 0 到 7 之間。
在下列範例中,將 Score
屬性設定為精確度 14,小數位數 2 會導致在 SQL Server 上建立類型 decimal(14,2)
的數據行,而將 LastUpdated
屬性設定為精確度 3 會導致類型為 datetime2(3)
的數據行:
public class Blog
{
public int BlogId { get; set; }
[Precision(14, 2)]
public decimal Score { get; set; }
[Precision(3)]
public DateTime LastUpdated { get; set; }
}
小數位數在未先定義精確度的情況下絕不會被定義,因此用於定義小數位數的數據註釋是 [Precision(precision, scale)]
。
Unicode
在某些關係資料庫中,有不同類型的代表 Unicode 和非 Unicode 文字數據。 例如,在 SQL Server 中,nvarchar(x)
用來代表 UTF-16 中的 Unicode 數據,而 varchar(x)
則用來表示非 Unicode 數據(但請參閱 SQL Server UTF-8 支援 上的注意事項)。 對於不支援此概念的資料庫,設定這沒有任何作用。
文字屬性預設會設定為 Unicode。 您可以將資料行設定為非 Unicode,如下所示:
public class Book
{
public int Id { get; set; }
public string Title { get; set; }
[Unicode(false)]
[MaxLength(22)]
public string Isbn { get; set; }
}
必要和選擇性屬性
當屬性能夠包含 null
時,它會被視為選擇性。 如果 null
不是指派給屬性的有效值,則會將其視為必要屬性。 對應至關係資料庫架構時,必要屬性會建立為不可為 Null 的數據行,而選擇性屬性會建立為可為 Null 的數據行。
約定
依照慣例,.NET 類型可以包含 Null 的屬性將會設定為選擇性,而 .NET 類型不能包含 Null 的屬性則會視需要設定。 例如,所有具有 .NET 實值型別的屬性(int
、decimal
、bool
等)都設定為必要,且所有具有可為 Null .NET 實值型別的屬性(int?
、decimal?
、bool?
等)都會設定為選擇性。
C# 8 引進了稱為 可為 Null 參考型別 (NRT)的新功能,其允許批注參考型別,指出它們是否有效,以包含 null。 這項功能預設會在新的專案範本中啟用,但除非明確選擇加入,否則在現有專案中會保持停用。 可空的參考型別會以下列方式影響 EF Core 的運作方式:
- 如果停用可為 Null 的參考型別,則具有 .NET 參考型別的所有屬性都會依慣例設為可選(例如,
string
)。 - 如果啟用可為 Null 的參考類型,則會根據其 .NET 類型的 C# 可為 Null 性來設定屬性:
string?
會設定為選擇性,但會視需要設定string
。
下列範例顯示了具有必要和選擇性屬性的實體類型,並分別展示了可為 Null 的參考功能在禁用和啟用時的情況。
- 沒有NRT(預設)
- 使用 NRT
public class CustomerWithoutNullableReferenceTypes
{
public int Id { get; set; }
[Required] // Data annotations needed to configure as required
public string FirstName { get; set; }
[Required] // Data annotations needed to configure as required
public string LastName { get; set; }
public string MiddleName { get; set; } // Optional by convention
}
建議使用可空參考型別,因為它可以將 C# 程式碼中表示的可空性傳遞到 EF Core 的模型和資料庫中,從而避免使用 Fluent API 或資料註解來重複表示相同的概念。
注意
在現有專案中啟用可為 Null 的參考型別時請謹慎:先前設定為選擇性的參考型別屬性現在將被設定為必要,除非它們被明確標註為可為 Null。 管理關係資料庫架構時,這可能會導致產生移轉,以更改資料庫欄位的可為空性。
如需有關可空性參考型別及其與 EF Core 使用方法的詳細資訊,請參閱此功能的專用文件頁面。
明確設定
根據慣例,屬性通常是可選的,但可以配置為必要屬性,如下所示:
public class Blog
{
public int BlogId { get; set; }
[Required]
public string Url { get; set; }
}
欄位排序規則
您可以在文字數據行上定義定序,以判斷其比較和排序方式。 例如,下列代碼段會將 SQL Server 資料行設定為不區分大小寫:
modelBuilder.Entity<Customer>().Property(c => c.Name)
.UseCollation("SQL_Latin1_General_CP1_CI_AS");
如果資料庫中的所有數據行都需要使用特定定序,請改為在資料庫層級定義定序。
如需 EF Core 對定序支援的一般資訊,請參閱 定序檔頁面。
欄位批注
您可以在資料庫資料行上設定任意文字評論,讓您在資料庫中記錄您的架構。
public class Blog
{
public int BlogId { get; set; }
[Comment("The URL of the blog")]
public string Url { get; set; }
}
欄位順序
根據預設,使用 Migrations建立數據表時,EF Core 會先排序主鍵數據行,後面接著實體類型和擁有類型的屬性,最後是基底類型的屬性。 不過,您可以指定不同的資料行順序:
public class EntityBase
{
[Column(Order = 0)]
public int Id { get; set; }
}
public class PersonBase : EntityBase
{
[Column(Order = 1)]
public string FirstName { get; set; }
[Column(Order = 2)]
public string LastName { get; set; }
}
public class Employee : PersonBase
{
public string Department { get; set; }
public decimal AnnualSalary { get; set; }
}
Fluent API 可用來覆寫使用屬性所做的順序,包括解決不同屬性的屬性指定相同順序號時所發生的任何衝突。
請注意,在一般情況下,大部分的資料庫只有在建立資料表時才支持排序資料行。 這表示數據行順序屬性無法用來重新排序現有數據表中的數據行。