我目前正在研究如何在我的Web应用程序中使用db4o存储。我很高兴db4o的工作原理。因此,当我阅读Code First方法时,我很喜欢,因为使用EF4 Code First的方式与使用db4o非常相似:创建域对象(POCO),将它们抛到db4o,永远不要回头。 / p>
但是当我进行性能比较时,EF 4的速度非常慢。我无法弄清楚原因。
我使用以下实体:
public class Recipe
{
private List _RecipePreparations;
public int ID { get; set; }
public String Name { get; set; }
public String Description { get; set; }
public List Tags { get; set; }
public ICollection Preparations
{ get { return _RecipePreparations.AsReadOnly(); } }
public void AddPreparation(RecipePreparation preparation)
{
this._RecipePreparations.Add(preparation);
}
}
public class RecipePreparation
{
public String Name { get; set; }
public String Description { get; set; }
public int Rating { get; set; }
public List Steps { get; set; }
public List Tags { get; set; }
public int ID { get; set; }
}
为了测试性能,我新建了一个配方,并添加了50.000 RecipePrepations。然后我将对象存储在db4o中,如下所示:
public void AddPreparation(RecipePreparation preparation)
{
this._RecipePreparations.Add(preparation);
}
}
这需要大约13.000(ms)
我将这些东西与EF4存储在SQL Server 2008(Express,本地)中,如下所示:
IObjectContainer db = Db4oEmbedded.OpenFile(Db4oEmbedded.NewConfiguration(), @"RecipeDB.db4o");
db.Store(recipe1);
db.Close();
这需要200.000(ms)
现在怎么样的db4o 15(!!!)快了EF4 / SQL?我错过了EF4的秘密涡轮按钮吗?我甚至认为db4o可以更快?由于我没有初始化数据库文件,我只是让它动态增长。
答案 0 :(得分:3)
您是否在循环中调用了SaveChanges()
?难怪它很慢!试着这样做:
foreach(var recipe in The500000Recipes)
{
cookRecipes.Recipes.Add(recipe);
}
cookRecipes.SaveChanges();
EF希望您全部进行所需的更改,然后再次调用SaveChanges
。这样,它可以优化数据库通信和sql来执行打开状态和保存状态之间的更改,忽略所有已撤消的更改。 (例如,添加50 000条记录,然后删除其中一半,然后点击SaveChanges
只会向数据库添加25 000条记录。永远。)
答案 1 :(得分:2)
也许你可以在添加新对象时禁用Changetracking,这确实会提高性能。
context.Configuration.AutoDetectChangesEnabled = false;
另请参阅更多信息:http://coding.abel.nu/2012/03/ef-code-first-change-tracking/
答案 2 :(得分:1)
EF擅长许多事情,但批量加载不是其中之一。如果您想要高性能批量加载,直接通过数据库服务器执行此操作将比任何 ORM更快。如果您的应用程序唯一的性能限制是批量加载,那么您可能不应该使用EF。
答案 3 :(得分:1)
只是添加其他答案:db4o通常在进程中运行,而EF抽象进程外(SQL)数据库。但是,db4o本质上是单线程的。因此,虽然对于具有一个请求的这个示例来说可能更快,但SQL将比默认的db4o数据库设置更好地处理并发(多个查询,多个用户)。