问题 为什么实体框架会对数据库进行如此多的往返?


我正在重写我的应用程序以使用实体框架。我感到困惑的是我写的代码看起来像是在sql server上做了不必要的三脚架。例如,我有一个类似于SO的问题答案网站。当我添加问题的答案时 - 这是我使用的代码:

var qu = context.question.where(c => c.questionID == 11).First();  //Database call here
var answer = new answer();
answer.title = "title here";
answer.desc = "desc here";
answer.question = qu;
context.SaveChanges();   //Database call here

在上面的代码中有2个数据库调用对吗?如果是这样,为什么我不能直接添加问题的答案?如

var ans = answer.Createanswer (0, "title here", "desc here", questionID)
context.SaveChanges();

有没有办法最小化所有数据库调用?


12855
2017-10-02 22:43


起源

好问题... - Alon Gubkin


答案:


正如EFJ设计师AlexJ所解释的那样 http://blogs.msdn.com/alexj/archive/2009/06/19/tip-26-how-to-avoid-database-queries-using-stub-entities.aspx

这一切都属于“优化”领域,而这种优化往往不像看起来那么简单

使用简单的方法,SQL将执行读取操作以加载FK(问题)并缓存结果,然后在单独的命令上执行应该使用缓存的FK结果的插入操作

使用附加的FK方法仍然会导致服务器对FK执行读操作,这意味着只需少一次往返SQL Server。所以问题就变成了 - 随着时间的推移,往返往往比增加的代码复杂性更昂贵?

如果应用程序和SQL Server在同一台机器上,则此开销非常小

此外,如果FK是大型或宽型表上的聚簇索引,则IO开销可能远远大于仅仅是FK值上的单独标准索引 - 假设查询优化器工作正常:-)


11
2017-10-02 23:28





您实际上不需要加载问题来设置关系。相反,您可以使用EntityReference

例如

Answer.QuestionReference = new EntityReference<Question>();
Answer.QuestionReference.EntityKey 
  = new EntityKey("MyContextName.Question", "Id", questionId); 

我个人使用扩展方法来设置实体键

public static void SetEntityKey<T>(this EntityReference value, int id)
{
   value.EntityKey = new EntityKey("ContextName." + typeof(T).Name, "Id", id);
}

所以它看起来会像这样。

 Answer.QuestionReference = new EntityReference<Question>();
 Answer.QuestionReference.SetEntityKey<Question>(questionId); 

8
2017-10-02 22:52



在调用SetEntityKey时,你不能使用'this EntityReference <T>'来避免显式<T>吗? - devio


它可以完成,但在.NET 3.5中非常痛苦。他们在.NET 4.0中更容易实现这一点。


-3
2017-10-02 22:52