# [Entity Framework 6] Database First 開發流程整理
## 前置作業
* 建立 Console 專案並安裝 Entity Framework 6
* 下載、建立範例資料庫:[CompanyDB.mdf](https://drive.google.com/file/d/1AvDY7d94b6kqFEI50arzvA4bOqmYB2uQ/view?usp=sharing)
## CompanyDB 簡介
CompanyDB,模擬公司組織架構,以圖表呈現如下圖:

**資料庫規劃說明**
* 資料表:`Staff`(員工)、`Information`(員工資料)、`Department`(部門)、`Project`(執行專案)、`StaffProject`(員工專案分配)
* 預存程序:`GetDepartmentProject`(取得部門進行中專案)
* 檢視表:`DepartmentStaff`(人員部門檢視)
## 開始使用 Entity Framework
在專案項目中點擊右鍵,選擇 **加入**=>**新增項目**,選擇 **ADO.NET實體資料模型**,名稱輸入 **Company**。

以資料庫優先的方式使用 Entity Framework,所以選擇 **來自資料庫的EF Designer**。

點擊 **新增連接**

輸入連線資料後,選擇剛才建立的範例資料庫

回到 選擇資料連接畫面後,點擊 下一步

將**資料表**、**檢視**、**預存程序和函式**打勾

完成之後在專案中會多了 Company.edmx 檔案
### Model Browser 查看 .edmx 檔案
在完成 Entity Framework 設定後,用 Model Browser 來觀看 Company.edmx

EDMX 說明:
* 圖表:資料庫關聯的圖表描述。
* 實體類型:資料表、檢視表的結構描述。
* 複雜類型:預存程式執行結果的結構描述。
* 函式匯入:資料庫的預存程序。
### CompanyDBEntities 簡介
```csharp=
public partial class CompanyDBEntities : DbContext
{
public CompanyDBEntities() : base("name=CompanyDBEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<Department> Department { get; set; }
public virtual DbSet<Information> Information { get; set; }
public virtual DbSet<Project> Project { get; set; }
public virtual DbSet<Staff> Staff { get; set; }
public virtual DbSet<DepartmentStaff> DepartmentStaff { get; set; }
public virtual ObjectResult<GetDepartmentProject_Result> GetDepartmentProject(string departmentID)
{
var departmentIDParameter = departmentID != null ?
new ObjectParameter("DepartmentID", departmentID) :
new ObjectParameter("DepartmentID", typeof(string));
return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<GetDepartmentProject_Result>("GetDepartmentProject", departmentIDParameter);
}
}
```
程式說明:
* 建構子指定連線字串名稱,連線字串記錄在 App.config 的 connectionStrings 區段。
* App.config 連線字串
```xml=
<connectionStrings>
<add name="CompanyDBEntities" connectionString="metadata=res://*/Company.csdl|res://*/Company.ssdl|res://*/Company.msl;provider=System.Data.SqlClient;provider connection string="data source=localhost;initial catalog=CompanyDB;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
</connectionStrings>
```
## 程式操作 CompanyDBEntities
* 印出員工姓名
```csharp=
using (CompanyDBEntities context = new CompanyDBEntities())
{
foreach (Staff staff in context.Staff)
{
Console.WriteLine(staff.Name);
}
}
```
* 印出各部門的員工姓名
```csharp=
using (CompanyDBEntities context = new CompanyDBEntities())
{
foreach (Department department in context.Department)
{
Console.WriteLine(department.Name);
foreach (Staff staff in department.Staff)
{
Console.WriteLine($"--{staff.Name}");
}
}
}
```
針對 Department 中的Staff 導覽屬性,Entity Framework 採取延遲載入,也就是當 Staff 資料被使用到時,才會向資料庫進行讀取。
## 呼叫預存程序
Entity Framework 提供資料的增刪查改操作,如果遇到較複雜的 SQL 操作,則可以透過寫好預存程序來執行 SQL 的語法操作。
範例資料庫建立好一個預存程序,查詢部門人員進行中的專案,名稱為 `GetDepartmentProject`,預存程序結果類別為`ObjectResult`。
```csharp=
using (CompanyDBEntities context = new CompanyDBEntities())
{
foreach (Department department in context.Department)
{
Console.WriteLine(department.Name);
ObjectResult departProject = context.GetDepartmentProject(department.ID);
foreach (GetDepartmentProject_Result result in departProject)
{
Console.WriteLine($"--{result.Name}:{result.Project}");
}
}
}
```
## 使用檢視表
```csharp=
using (CompanyDBEntities context = new CompanyDBEntities())
{
foreach (DepartmentStaff departmentStaff in context.DepartmentStaff)
{
Console.WriteLine($"{departmentStaff.Department},{departmentStaff.Staff}");
}
}
```
###### tags: `Entity Framework` `Database First`