我花了大量時間來彎曲實體框架,以我的需求,因此可以說,它符合大多數你從一個ORM想要的要求。但有些方面太複雜了,因爲其他ORM已經表明它可以變得更容易。
例如,開始使用Entity Framework相當容易,因爲您可以在Visual Studio中啓動Designer並在幾分鐘內啓動一個可用的ORM。但是最終會得到與設計者創建的ObjectContext綁定的實體類(這可以使用自定義的T4模板來避免)。這不是一件壞事,但它就是那種微軟的「入門」方法,你不想在真正的應用程序中使用。
但是,如果您深入瞭解實體框架,您可以看到如何避免大部分缺陷:設計器生成一個EDMX文件,該文件(如果您在XML編輯器中查看)只不過是一個ORM的三個主要方面,物理存儲(您的數據庫),概念模型(您的實體類)以及它們之間的映射的組合。在Visual Studio中應用於.edmx文件的自定義構建操作會將這3個部分分割爲三個單獨的文件,並將它們作爲嵌入式資源添加到程序集中。當創建一個ObjectContext時,ConnectionString中使用這三個文件的路徑(這對我來說總是有點混亂)。你可以在這裏做的是你自己做的。這意味着在XML編輯器中編寫存儲模式,概念模型和映射(很像NHibernate),並將其嵌入到包含模型的程序集中。
基本實體框架基類「ObjectContext」可以從這三個文件構建(它需要MetadataWorkspace和EntityConnection),但重點是,您可以完全控制如何創建ObjectContext。這爲您可能無法從Entity Framework期望的許多功能打開了大門。例如:可以在同一個程序集中嵌入多個SSDL存儲模式以匹配特定的數據庫類型(我通常爲SQL Server添加一個,而爲SQL Server CE 4.0添加一個)。並創建一個構造函數重載,爲特定類型的DbConnection選擇適當的存儲模式。
由於您現在擁有自己的ObjectContext實現,因此您可以在其上實現各種接口。你自己喜歡IRepository,但因爲我喜歡ObjectContext的方法,我創造這樣:
interface ICatalog
{
IEntitySet<Article> { get; }
void Save();
}
interface IEntitySet<T> : IQueryable<T>
{
void Add(T);
void Remove(T);
}
class EntityFrameworkCatalog : ICatalog
{
...
}
但創建一個存儲庫,如果你有一個實體框架ObjectContext的是很容易,再加上你得到一個IQueryable。基於這些信息,您可以避免在服務和ORM之間產生強大的類耦合,並在測試中完整地剔除實體框架。此外,在測試實體框架實施時,您可以在單元測試期間使用SQL Server CE數據庫,以確保映射無誤(通常,CE和完整SQL Server的存儲模式之間的差異僅僅是一些數據 - 類型)。所以你可以實際測試你的實體框架實現的所有行爲。
這使得Entity Framework可以很好地與現代的軟件概念一起使用,但它不會對您實施這樣的實踐,這使得「入門」變得更加簡單。
現在到了複雜的位:實體框架有一小組受支持的CLR類型,基本上只包括原始類型,如int,字符串和字節數組。它還提供了一些複雜類型,遵循相同的規則。但是,如果你有一個複雜的實體屬性,比如文檔的DOM表示,你想在數據庫中序列化爲XML。據我所知,NHibernate提供了一個名爲IUserType的功能,它允許你爲你定義這樣的映射。在實體框架中,這變得更加複雜,但它仍然以它自己的方式非常漂亮。概念模型允許你包含程序集內部的複雜類型(只要你告訴ObjectContext它就可以了(ObjectContext.CreateProxyTypes(Type []))。所以你可以爲你的原始類型創建一個包裝,這只是已知的實體框架,像這樣:
class Document : IXmlSerializable { }
class Article
{
public virtual Document Content { get; set; }
}
internal class EntityFrameworkDocument : Document
{
public string Xml
{
get
{
// Use XmlSerializer to generate the XML-string for this instance.
}
set
{
// Use XmlSerializer to read the XML-string for this instance.
}
}
}
Altough的EF現在可以從存儲返回的序列化文件,將它們寫入它,需要你攔截物品的存儲和與EntityFrameworkDocument更換一個簡單的文檔,以確保EF可以序列化它我確信其他ORMs很容易做到這一點,它變得更糟,目前沒有辦法,做System.Uri類(這是不可改變的,但否則工作)或一個Enum除了這些限制之外,您還可以根據您的大部分需求來配置EF生病花費了很多時間(就像我做的那樣)。
因爲我與其他的ORM的經驗是有限的,我會總結:
- 實體框架是在GAC中,即使在客戶端配置文件
- 實體框架可以定製,以代表甚至複雜的實體類型(包括一些自引用許多一對多例如,或者上面的XML序列化)
- 它可以是「抽象」的,所以你能堅持到IRepository等
- IQueryable的執行(altough它不是完整的作爲DataObjects.Net)
它只需要System.Data和System.Data.Entity的,你甚至可以包括其他供應商,這通常需要參考多種存儲模式,但如果你堅持的DbConnection你可以這樣做:
ICatalog Create(DbConnection connection, string storageSchemaPath) ICatalog CreateMySql(DbConnection mySqlConnection) { return Create(connection, "res://Assembly/Path.To.Embedded.MySql.Storage.ssdl"); }
編輯 最近我發現,如果你的實體和你的「目錄」的實施是在同一個組件,您可以使用內部屬性的XML序列化過程。因此,不要從Document
派生內部EntityFrameworkDocument
,而是可以將名爲Xml
的內部屬性添加到Document
類本身。這仍然只適用於完全控制實體的情況,但它不需要攔截對目錄的任何更改,以確保使用派生類。 CSDL看起來一樣,EF只允許映射的屬性是內部的。我仍然必須確保這可以在中等信任環境下工作。
可能重複(http://stackoverflow.com/questions/1377236/nhibernate-entity-framework-active-records-or-linq2sql) – 2011-02-24 16:22:13
除了之一是從09年9月份開始,EF – 2011-02-24 17:21:51
的變化很大我對這個問題的回答在2010年6月更新,從那時起EF4或其他ORM沒有多大變化。無論如何,你不應該因爲想要更新鮮的答案而造成重複的問題。 – 2011-02-25 11:47:17