Fluent API 與 VB.NET
Code First 可讓您使用 C# 或 VB.NET 類別來定義模型。 您也可以選擇性地使用類別和屬性上的屬性或使用 Fluent API 來執行其他設定。 本逐步解說示範如何使用 VB.NET 執行 Fluent API 組態。
此頁面假設您已基本瞭解 Code First。 如需 Code First 的詳細資訊,請參閱下列逐步解說:
必要條件
您必須至少安裝 Visual Studio 2010 或 Visual Studio 2012,才能完成本逐步解說。
如果您使用 Visual Studio 2010,您也必須 安裝 NuGet
建立應用程式
為了簡化工作,我們將建置使用 Code First 執行資料存取的基本主控台應用程式。
- 開啟 Visual Studio
- 檔案 - > 新增 - > 專案...
- 從左側功能表選取 [Windows ] 和 [主控台應用程式]
- 輸入 CodeFirstVBSample 作為名稱
- 選取確定
定義模型
在此步驟中,您將定義代表概念模型的 POCO 實體類型 VB.NET。 類別不需要衍生自任何基類或實作任何介面。
- 將新類別新增至專案,輸入 SchoolModel 作為類別名稱
- 以下列程式碼取代新類別的內容
Public Class Department
Public Sub New()
Me.Courses = New List(Of Course)()
End Sub
' Primary key
Public Property DepartmentID() As Integer
Public Property Name() As String
Public Property Budget() As Decimal
Public Property StartDate() As Date
Public Property Administrator() As Integer?
Public Overridable Property Courses() As ICollection(Of Course)
End Class
Public Class Course
Public Sub New()
Me.Instructors = New HashSet(Of Instructor)()
End Sub
' Primary key
Public Property CourseID() As Integer
Public Property Title() As String
Public Property Credits() As Integer
' Foreign key that does not follow the Code First convention.
' The fluent API will be used to configure DepartmentID_FK to be the foreign key for this entity.
Public Property DepartmentID_FK() As Integer
' Navigation properties
Public Overridable Property Department() As Department
Public Overridable Property Instructors() As ICollection(Of Instructor)
End Class
Public Class OnlineCourse
Inherits Course
Public Property URL() As String
End Class
Partial Public Class OnsiteCourse
Inherits Course
Public Sub New()
Details = New OnsiteCourseDetails()
End Sub
Public Property Details() As OnsiteCourseDetails
End Class
' Complex type
Public Class OnsiteCourseDetails
Public Property Time() As Date
Public Property Location() As String
Public Property Days() As String
End Class
Public Class Person
' Primary key
Public Property PersonID() As Integer
Public Property LastName() As String
Public Property FirstName() As String
End Class
Public Class Instructor
Inherits Person
Public Sub New()
Me.Courses = New List(Of Course)()
End Sub
Public Property HireDate() As Date
' Navigation properties
Private privateCourses As ICollection(Of Course)
Public Overridable Property Courses() As ICollection(Of Course)
Public Overridable Property OfficeAssignment() As OfficeAssignment
End Class
Public Class OfficeAssignment
' Primary key that does not follow the Code First convention.
' The HasKey method is used later to configure the primary key for the entity.
Public Property InstructorID() As Integer
Public Property Location() As String
Public Property Timestamp() As Byte()
' Navigation property
Public Overridable Property Instructor() As Instructor
End Class
定義衍生的內容
我們即將開始使用 Entity Framework 中的類型,因此我們需要新增 EntityFramework NuGet 套件。
- **專案 – > 管理 NuGet 套件...
注意
如果您沒有 [管理 NuGet 套件...] 選項,您應該安裝 最新版本的 NuGet
- 選取 [線上] 索引 標籤
- 選取 EntityFramework 套件
- 按一下 [安裝]
現在是時候定義衍生內容,其代表與資料庫的會話,讓我們能夠查詢和儲存資料。 我們會定義衍生自 System.Data.Entity.DbCoNtext 的內容,並公開模型中每個類別的具型別 DbSet < TEntity > 。
- 將新類別新增至專案,輸入 SchoolCoNtext 作為類別名稱
- 以下列程式碼取代新類別的內容
Imports System.ComponentModel.DataAnnotations
Imports System.ComponentModel.DataAnnotations.Schema
Imports System.Data.Entity
Imports System.Data.Entity.Infrastructure
Imports System.Data.Entity.ModelConfiguration.Conventions
Public Class SchoolContext
Inherits DbContext
Public Property OfficeAssignments() As DbSet(Of OfficeAssignment)
Public Property Instructors() As DbSet(Of Instructor)
Public Property Courses() As DbSet(Of Course)
Public Property Departments() As DbSet(Of Department)
Protected Overrides Sub OnModelCreating(ByVal modelBuilder As DbModelBuilder)
End Sub
End Class
使用 Fluent API 進行設定
本節示範如何使用 Fluent API,將類型設定為數據表對應、屬性與資料行對應,以及模型中 tables\type 之間的關聯性。 Fluent API 會透過 DbModelBuilder 類型公開,而且最常透過覆寫 DbCoNtext 上的 OnModelCreating 方法來存取。
- 複製下列程式碼,並將其新增至 SchoolCoNtext 類別上 定義的 OnModelCreating 方法 批註說明每個對應的功能
' Configure Code First to ignore PluralizingTableName convention
' If you keep this convention then the generated tables
' will have pluralized names.
modelBuilder.Conventions.Remove(Of PluralizingTableNameConvention)()
' Specifying that a Class is a Complex Type
' The model defined in this topic defines a type OnsiteCourseDetails.
' By convention, a type that has no primary key specified
' is treated as a complex type.
' There are some scenarios where Code First will not
' detect a complex type (for example, if you do have a property
' called ID, but you do not mean for it to be a primary key).
' In such cases, you would use the fluent API to
' explicitly specify that a type is a complex type.
modelBuilder.ComplexType(Of OnsiteCourseDetails)()
' Mapping a CLR Entity Type to a Specific Table in the Database.
' All properties of OfficeAssignment will be mapped
' to columns in a table called t_OfficeAssignment.
modelBuilder.Entity(Of OfficeAssignment)().ToTable("t_OfficeAssignment")
' Mapping the Table-Per-Hierarchy (TPH) Inheritance
' In the TPH mapping scenario, all types in an inheritance hierarchy
' are mapped to a single table.
' A discriminator column is used to identify the type of each row.
' When creating your model with Code First,
' TPH is the default strategy for the types that
' participate in the inheritance hierarchy.
' By default, the discriminator column is added
' to the table with the name “Discriminator”
' and the CLR type name of each type in the hierarchy
' is used for the discriminator values.
' You can modify the default behavior by using the fluent API.
modelBuilder.Entity(Of Person)().
Map(Of Person)(Function(t) t.Requires("Type").
HasValue("Person")).
Map(Of Instructor)(Function(t) t.Requires("Type").
HasValue("Instructor"))
' Mapping the Table-Per-Type (TPT) Inheritance
' In the TPT mapping scenario, all types are mapped to individual tables.
' Properties that belong solely to a base type or derived type are stored
' in a table that maps to that type. Tables that map to derived types
' also store a foreign key that joins the derived table with the base table.
modelBuilder.Entity(Of Course)().ToTable("Course")
modelBuilder.Entity(Of OnsiteCourse)().ToTable("OnsiteCourse")
modelBuilder.Entity(Of OnlineCourse)().ToTable("OnlineCourse")
' Configuring a Primary Key
' If your class defines a property whose name is “ID” or “Id”,
' or a class name followed by “ID” or “Id”,
' the Entity Framework treats this property as a primary key by convention.
' If your property name does not follow this pattern, use the HasKey method
' to configure the primary key for the entity.
modelBuilder.Entity(Of OfficeAssignment)().
HasKey(Function(t) t.InstructorID)
' Specifying the Maximum Length on a Property
' In the following example, the Name property
' should be no longer than 50 characters.
' If you make the value longer than 50 characters,
' you will get a DbEntityValidationException exception.
modelBuilder.Entity(Of Department)().Property(Function(t) t.Name).
HasMaxLength(60)
' Configuring the Property to be Required
' In the following example, the Name property is required.
' If you do not specify the Name,
' you will get a DbEntityValidationException exception.
' The database column used to store this property will be non-nullable.
modelBuilder.Entity(Of Department)().Property(Function(t) t.Name).
IsRequired()
' Switching off Identity for Numeric Primary Keys
' The following example sets the DepartmentID property to
' System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.None to indicate that
' the value will not be generated by the database.
modelBuilder.Entity(Of Course)().Property(Function(t) t.CourseID).
HasDatabaseGeneratedOption(DatabaseGeneratedOption.None)
'Specifying NOT to Map a CLR Property to a Column in the Database
modelBuilder.Entity(Of Department)().
Ignore(Function(t) t.Administrator)
'Mapping a CLR Property to a Specific Column in the Database
modelBuilder.Entity(Of Department)().Property(Function(t) t.Budget).
HasColumnName("DepartmentBudget")
'Configuring the Data Type of a Database Column
modelBuilder.Entity(Of Department)().Property(Function(t) t.Name).
HasColumnType("varchar")
'Configuring Properties on a Complex Type
modelBuilder.Entity(Of OnsiteCourse)().Property(Function(t) t.Details.Days).
HasColumnName("Days")
modelBuilder.Entity(Of OnsiteCourse)().Property(Function(t) t.Details.Location).
HasColumnName("Location")
modelBuilder.Entity(Of OnsiteCourse)().Property(Function(t) t.Details.Time).
HasColumnName("Time")
' Map one-to-zero or one relationship
' The OfficeAssignment has the InstructorID
' property that is a primary key and a foreign key.
modelBuilder.Entity(Of OfficeAssignment)().
HasRequired(Function(t) t.Instructor).
WithOptional(Function(t) t.OfficeAssignment)
' Configuring a Many-to-Many Relationship
' The following code configures a many-to-many relationship
' between the Course and Instructor types.
' In the following example, the default Code First conventions
' are used to create a join table.
' As a result the CourseInstructor table is created with
' Course_CourseID and Instructor_InstructorID columns.
modelBuilder.Entity(Of Course)().
HasMany(Function(t) t.Instructors).
WithMany(Function(t) t.Courses)
' Configuring a Many-to-Many Relationship and specifying the names
' of the columns in the join table
' If you want to specify the join table name
' and the names of the columns in the table
' you need to do additional configuration by using the Map method.
' The following code generates the CourseInstructor
' table with CourseID and InstructorID columns.
modelBuilder.Entity(Of Course)().
HasMany(Function(t) t.Instructors).
WithMany(Function(t) t.Courses).
Map(Sub(m)
m.ToTable("CourseInstructor")
m.MapLeftKey("CourseID")
m.MapRightKey("InstructorID")
End Sub)
' Configuring a foreign key name that does not follow the Code First convention
' The foreign key property on the Course class is called DepartmentID_FK
' since that does not follow Code First conventions you need to explicitly specify
' that you want DepartmentID_FK to be the foreign key.
modelBuilder.Entity(Of Course)().
HasRequired(Function(t) t.Department).
WithMany(Function(t) t.Courses).
HasForeignKey(Function(t) t.DepartmentID_FK)
' Enabling Cascade Delete
' By default, if a foreign key on the dependent entity is not nullable,
' then Code First sets cascade delete on the relationship.
' If a foreign key on the dependent entity is nullable,
' Code First does not set cascade delete on the relationship,
' and when the principal is deleted the foreign key will be set to null.
' The following code configures cascade delete on the relationship.
' You can also remove the cascade delete conventions by using:
' modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>()
' and modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>().
modelBuilder.Entity(Of Course)().
HasRequired(Function(t) t.Department).
WithMany(Function(t) t.Courses).
HasForeignKey(Function(d) d.DepartmentID_FK).
WillCascadeOnDelete(False)
使用模型
讓我們使用 SchoolCoNtext 執行一些資料存取,以查看作用中的模型。
- 開啟定義 Main 函式的 Module1.vb 檔案
- 複製並貼上下列 Module1 定義
Imports System.Data.Entity
Module Module1
Sub Main()
Using context As New SchoolContext()
' Create and save a new Department.
Console.Write("Enter a name for a new Department: ")
Dim name = Console.ReadLine()
Dim department = New Department With { .Name = name, .StartDate = DateTime.Now }
context.Departments.Add(department)
context.SaveChanges()
' Display all Departments from the database ordered by name
Dim departments =
From d In context.Departments
Order By d.Name
Select d
Console.WriteLine("All Departments in the database:")
For Each department In departments
Console.WriteLine(department.Name)
Next
End Using
Console.WriteLine("Press any key to exit...")
Console.ReadKey()
End Sub
End Module
您現在可以執行應用程式並進行測試。
Enter a name for a new Department: Computing
All Departments in the database:
Computing
Press any key to exit...