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

use*_*433 11 c# asp.net-mvc linq-to-entities entity-framework

我正在重写我的应用程序以使用实体框架.我感到困惑的是我写的代码看起来像是在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
Run Code Online (Sandbox Code Playgroud)

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

var ans = answer.Createanswer (0, "title here", "desc here", questionID)
context.SaveChanges();
Run Code Online (Sandbox Code Playgroud)

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

TFD*_*TFD 11

正如AlexJ设计师之一所解释的那样,EF设计师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值上的单独标准索引 - 假设查询优化器工作正常:-)


小智 8

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

例如

Answer.QuestionReference = new EntityReference<Question>();
Answer.QuestionReference.EntityKey 
  = new EntityKey("MyContextName.Question", "Id", questionId); 
Run Code Online (Sandbox Code Playgroud)

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

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

所以它看起来像这样.

 Answer.QuestionReference = new EntityReference<Question>();
 Answer.QuestionReference.SetEntityKey<Question>(questionId); 
Run Code Online (Sandbox Code Playgroud)