2010年8月6日星期五

Entity Framework 4.0 : No support for Auto-increment primary keys

EF4是一個不錯的ORM,配搭SQL Server是無敵的組合,但如果用EF4配合SQLCE的話,你可能要重新考慮一下。


無論LINQ2SQL或EF4,一個Table的Primary Key/Unique Key都很重要,因為做Insert/Update/Delete時,在SubmitChange()之前,.NET Framework就會用identifier把需要修改的Entity記起。
一般情況下,Create Table很自然會把id設定做INT / PrimaryKey / IDENTITY(1,1),但如果是SQLCE的話,會怎麼樣呢?

當你使用VS內建的Generator建立EntityModel *.edmx都沒有問題的,但只要你一做修改,就會出現Error
NotSupportedException Message=Server-generated keys and server-generated values are not supported by SQL Server Compact.

原因在Technet已經有解釋:
SQL Server Compact does not support entities with server-generated keys or values when it is used with the Entity Framework. When using the Entity Framework, an entity’s keys may be marked as server generated. This enables the database to generate a value for the key on insertion or entity creation. Additionally, zero or more properties of an entity may be marked as server-generated values. For more information, see the Store Generated Pattern topic in the Entity Framework documentation. SQL Server Compact does not support entities with server-generated keys or values when it is used with the Entity Framework, although the Entity Framework allows you to define entity types with server-generated keys or values. Data manipulation operation on an entity that has server-generated values throws a "Not supported" exception.

唯一解決方法,就是把INT轉做uniqueidentifier類型,而Default value設定做NEWID(),那每次新增一個紀錄就會自行輸入新的Row ID。


在程式碼方面,無論LINQ2SQL或EF4.0都會把uniqueidentifier的資料類型視為GUID (順便一提,GUID全名是Microsoft's Globally Unique Identifiers,和GUI (graphical user interface)無關),所以如果要做Where的程序時,就必須把Value轉成GUID,例如 :
private void cbAccount_SelectionChanged(object sender, SelectionChangedEventArgs e) {
dataEntities de = new dataEntities(EntityConn);
Guid guid = new Guid(cbAccount.SelectedValue.ToString());
var select = from val in de.account_value where val.account_id.Equals(guid) select val;
foreach (account_value v in select) { Console.WriteLine(v.value); }
}

或者有人擔心重覆的問題,大家可以看看維基百科,都幾有趣的。
與被隕石擊中的機率比較的話,已知一個人每年被隕石擊中的機率估計為170億分之1,等同於在一年內建立數十兆筆UUID並發生一次重複。換句話說,每秒產生10億筆UUID,100年後只產生一次重複的機率是50%。如果地球上每個人都各有6億筆UUID,發生一次重複的機率是50%。

其實我個人都有點不太認同把EF不支援INT類型的PrimaryKey,因為實際使用上,uniqueidentifier的確不方便,在我網上Research的同時,很多人都寧願使用回傳統SQL就算。

沒有留言:

發佈留言