公司原來用nhibernate,如今考慮要不要換一種ORM,因而找來了EF和ServiceStack.OrmLite。因此就產生了測試這三個性能的要求。對比三個ORM工具的性能,主要是對比ORM配置和啓動速度;建錶速度;插入行速度;修改行速度以及查詢速度,刪除用的比較少,就不測試了,還有發現EF貌似比nhibernate稍微快一些,就只測EF和ServiceStack.OrmLite了。sql
public class School { public Guid ID { get; set; } public string Name { get; set; } public int AllPersonCount { get; set; } } public class Person { public long ID { get; set; } public string Name { get; set; } public int Age { get; set; } public School InShool { get; set; } }
1. 插入10個學校, 學校人數從1遞增,名稱相同爲」SSS」
2. 每一個學校插入1000人,年齡從1遞增,名字相同」PPP」,並返回ID
3. 查詢年齡大於30的人
4. 更新3查詢出的人的年齡到當前值加20
5. 查詢學校人數大於5的全部人
6. 統計學校人數大於5的全部人的人數數據庫
1. 儘可能簡潔
2. 不能使用sql語句併發
nhibernate是由另外一個傢伙搞,我就寫EF的測試代碼。首先新建一個控制檯應用程序,右鍵項目管理NuGet添加EF6.1.3。而後新建那兩個表對應的類,接着就開始一個個寫啦。下面每種的兩個代碼段上面的是EF的,下面的是ServiceStack.OrmLite的ide
watch.Start(); db = new TestContext(); watch.Stop(); Console.WriteLine("ORM配置及啓動:" + watch.ElapsedMilliseconds);
watch.Start(); OrmLiteConfig.DialectProvider = SqlServerDialect.Provider; string connStr = ConfigurationManager.ConnectionStrings["SSConnection"].ConnectionString; db = connStr.OpenDbConnection(); watch.Stop(); Console.WriteLine("ORM配置及啓動:" + watch.ElapsedMilliseconds);
watch.Restart(); db.Database.Initialize(true); watch.Stop(); Console.WriteLine("建表:" + watch.ElapsedMilliseconds);
watch.Restart(); db.CreateTable<School>(); db.CreateTable<Person>(); watch.Stop(); Console.WriteLine("建表:" + watch.ElapsedMilliseconds);
db.Configuration.AutoDetectChangesEnabled = false; db.Configuration.ValidateOnSaveEnabled = false; watch.Restart(); for (int i = 1; i < 11; i++) { db.School.Add(new School { ID = Guid.NewGuid(), Name = "SSS", AllPersonCount = i }); } db.SaveChanges(); watch.Stop(); Console.WriteLine("測試項目1:" + watch.ElapsedMilliseconds);
watch.Restart(); var schools = new List<School>(); for (int i = 1; i < 11; i++) { schools.Add(new School { ID = Guid.NewGuid(), Name = "SSS", AllPersonCount = i }); } db.InsertAll(schools); watch.Stop(); Console.WriteLine("測試項目1:" + watch.ElapsedMilliseconds);
watch.Restart(); List<School> schools = db.School.ToList(); schools.ForEach(o => { for (int i = 1; i < 1001; i++) { db.Person.Add(new Person { Age = i, Name = "PPP", InShool = o }); } }); db.SaveChanges(); watch.Stop(); Console.WriteLine("測試項目2:" + watch.ElapsedMilliseconds);
schools = db.LoadSelect<School>(); watch.Restart(); var students = new List<Person>(); schools.ForEach(o => { for (int i = 1; i < 1001; i++) { students.Add(new Person { Age = i, Name = "PPP", ShoolID = o.ID }); } }); db.InsertAll(students); watch.Stop(); Console.WriteLine("測試項目2:" + watch.ElapsedMilliseconds);
db.Configuration.AutoDetectChangesEnabled = true; watch.Restart(); List<Person> person = db.Person.Where(o => o.Age > 30).ToList(); watch.Stop(); Console.WriteLine("測試項目3:" + watch.ElapsedMilliseconds);
watch.Restart(); List<Person> persons = db.Select<Person>(x => x.Age > 30); watch.Stop(); Console.WriteLine("測試項目3:" + watch.ElapsedMilliseconds);
watch.Restart(); person.ForEach(o => o.Age += 20); db.SaveChanges(); watch.Stop(); Console.WriteLine("測試項目4:" + watch.ElapsedMilliseconds);
watch.Restart(); persons.ForEach(o => o.Age += 20); db.UpdateAll(persons); watch.Stop(); Console.WriteLine("測試項目4:" + watch.ElapsedMilliseconds);
watch.Restart(); List<Person> students = db.Person.AsNoTracking().Where(o => o.InShool.AllPersonCount > 5).ToList(); watch.Stop(); Console.WriteLine("測試項目5:" + watch.ElapsedMilliseconds);
watch.Restart(); students = db.Select( db.From<Person>() .Join<School>((p, s) => p.ShoolID == s.ID) .Where<School>(s => s.AllPersonCount > 5) ); watch.Stop(); Console.WriteLine("測試項目5:" + watch.ElapsedMilliseconds);
watch.Restart(); int count = db.Person.Count(o => o.InShool.AllPersonCount > 5); watch.Stop(); Console.WriteLine("測試項目6:" + watch.ElapsedMilliseconds);
watch.Restart(); long count = db.Count( db.From<Person>() .Join<School>((p, s) => p.ShoolID == s.ID) .Where<School>(s => s.AllPersonCount > 6) ); watch.Stop(); Console.WriteLine("測試項目6:" + watch.ElapsedMilliseconds);
這裏要說明一下的是測試項目5和6的人數大於5是說學校表的AllPersonCount大於5,並且那個字段並非真的學生總人數,不會隨學生的增長而增長,只是爲了測試的。工具
EF運行3次的截圖以下:性能
ServiceStack.OrmLite運行3次的截圖以下:測試
接下來要開大招了,學校從加10個改成加100個,這樣的話學生就會從10000個增長到100000個,插入10萬行的時候nhibernate直接頂不住了。ui
EF運行3次的截圖以下:spa
ServiceStack.OrmLite運行3次的截圖以下:hibernate
須要說明的是數據庫是mssql2008,而且程序和數據庫都在本機,不一樣的電腦的性能不同,數據庫不同也會影響測試的結果,因此你們若是要對比其餘ORM工具的話,須要把多個程序在同一個電腦上運行,而且鏈接同一個數據庫。經過對比能夠發現,輕量級的OrmLite最快,EF和nhiberate差很少快,EF稍佔優點。不過併發能力的話卻是還沒測試過,不知道那個更好。