也許有人問,為什麼要用EF建立愛你資料表,code first好處是什嗎?
使用EF建立資料庫/表,只需要設計簡單的C#類,再表內容變化的時候他會自動更新資料庫結構,並且保留原有資料。
EF很強大,支援主外鍵並且能產生和db裡一樣的資料類型。由於我們這兩個表簡單,關於進階的知識我會放在這篇文章的底部作為附錄。
根據需求,我們有兩種 input 檔案。一種是trend 的一種是bar的 我們先來看看這兩種檔案裡的資料:
Trend :
id taskid taskname time b1 equal b2 uncertain grandtotal 0 1 task1 2012-6-27 200 300 280 220 1000
Bar :
KeyWord B1Better Equal B2Better Winner 聯眾 2 0 3 0 0 B1 瘋狂倒計時 0 0 3 0 0 B2 張娜拉 0 1 2 2 0 B1 軟體 1 0 1 1 2 B2
我們需要show 2個 chart。
那麼我們設計2個表來儲存 trend chart 和barchart 的資料,名為Trend 和Bar(本來應該是3個表。由於我們是為了自己練習,設計2個就好。)
到這裡,我才發現我們還沒為我們的project 起名字呢。叫什麼好呢?我們就叫 ReportingSyncer吧。
Reporting(報表),sync(同步),為什麼加er?現在的project 命名的時候往往都擬人化,顯得生動外加比較給力。
【開始動手】
開啟vs 2010建立一個新的class library 命名為ReportingDBManager。刪除自動產生的class1.cs 。
修改sln(解決方案的名稱為ReportingSyncer)。
修改命名空間:右鍵點擊ReportingDBManager。properties(屬性)->Application:CnBlogsDemos.ReportingDBManager。為啥要改?因為引用起來方便一點,而且也顯得專業:)
現在你的sln應該是這樣
添加Entity Framework 引用,得到這個dll 有兩種方法:
使用NuGet ,或者去下載一個dll。在這裡我使用Nuget ,EF最新版是4.3.1
【建立表的映射類】
添加完引用之後,我們就開始建立我們的表類了。
添加兩個class ,名為 Trend 和 Bar。
對應上邊input 檔案的類型,我們設計兩張 匹配的表。
bar.cs:
namespace CnBlogsDemos.ReportingDBManager{ using System.ComponentModel; using System.ComponentModel.DataAnnotations; public class Bar { [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] //主鍵 自增 public int ID { get; set; }public int TaskID { get; set; } [MaxLength(200)] public string TaskName { get; set; } /*有朋友要問了,匯入檔案裡明明沒有以上兩個欄位,為什麼要設定他們? 因為匯入的時候是根據每個task 匯入的,我們會在commandline裡資料task id 和task name 這樣才可以讓兩個表聯絡起來,後期好做報表的drill down (鑽入) */ [MaxLength(500)] public string KeyWord { get; set; } public int B1Better { get; set; } public int Equal { get; set; } public int B2Better { get; set; } [MaxLength(50)] public string Winner { get; set; } public string type { get; set; } [DefaultValue(true)] public bool IsActive { get; set; } }}
trend.cs
namespace CnBlogsDemos.ReportingDBManager{ using System; using System.ComponentModel; using System.ComponentModel.DataAnnotations; public class Trend { public int id { get; set; } public int TaskID { get; set; } public string TaskName { get; set; } public DateTime Time { get; set; } public int B1Better { get; set; } public int Equal { get; set; } public int B2Better { get; set; } public int UnCertain { get; set; } public int GrandTotal { get; set; } [MaxLength(50)] public string type { get; set; } [DefaultValue(true)] public bool IsActive { get; set; } }}
兩個表類建立好了。如何和資料庫聯絡到一塊呢?我們需要使用EF建立一個dbcontext類了。
添加新類:DbStoreContext.cs
namespace CnBlogsDemos.ReportingDBManager{ using System.Data.Entity; using System.Data.Entity.Migrations; internal sealed class ReportingDbMigrationsConfiguration : DbMigrationsConfiguration<DbStoreContext> { public ReportingDbMigrationsConfiguration() { AutomaticMigrationsEnabled = true; AutomaticMigrationDataLossAllowed = true; } } public class DbStoreContext : DbContext { public DbStoreContext() : base("name=ReportingDataBase") { Database.SetInitializer<DbStoreContext>( new MigrateDatabaseToLatestVersion<DbStoreContext, ReportingDbMigrationsConfiguration>()); this.Configuration.LazyLoadingEnabled = false; } public DbSet<Bar> Bars { get; set; } public DbSet<Trend> Trends { get; set; } }}
上邊的兩個Dbset 就是我們要建立的兩個表。
檢查項目中app.config檔案,我們會看到:
<entityFramework> <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework"> <parameters> <parameter value="Data Source=.\SQLEXPRESS; Integrated Security=True; MultipleActiveResultSets=True" /> </parameters> </defaultConnectionFactory> </entityFramework>
EF預設指定的資料庫是本地的Express。我們可以更改成其他標準資料庫或者是遠端資料庫(當然,你要有許可權哦)。
我們想在另一個project 裡指定資料庫連接。先把這個appconfig刪除。
有朋友要問了,什麼時候能產生DB,table啊?我怎麼看不見?
別急,在我們第一次調用這個dbcontext 類的時候就會建立/更新啦!
我會在下一章做講解。
【附錄】
EF建立table 時候的一些技巧,查了好多資料,希望能協助大家:
主鍵:
[Key]public int EngineID { get; set; }
自增主鍵:
[Key,DatabaseGenerated(DatabaseGeneratedOption.None)]public int EngineID { get; set; }
可以編輯的主鍵(預設是readonly)
[Key,Editable(true),DatabaseGenerated(DatabaseGeneratedOption.None)]public int EngineID { get; set; }
非空欄位:
[Required] public string EngineName { get; set; }
限定長度的非空欄位:
[Required, MaxLength(256)] public string EngineName { get; set; }
外鍵比較特殊,需要解釋一下兩個table之間的關係。
table1包含 一個 欄位 taskID。
table task 的主鍵是taskID。需要建立愛你一個 task類型的欄位。關係如下:
public class Table1{ [Required, ForeignKey("Task")] public int TaskID { get; set; } public virtual Task Task { get; set; }}public class Task{ [Key,DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int TaskID { get; set; }}
時間戳記:
[ConcurrencyCheck] 1544158309 public byte[] TimeStamp { get; set; }
c# 裡的 int32 對應 db 裡的int 。int16 對應 smallint,bool 對應bit,byte[]對應binary等等。