2011-06-07 66 views
2

我发现使用Linq-to-SQL创建新对象时,只有在调用SubmitChanges之后才能访问外键成员新对象“正在创建”的上下文。当然,我明白,在将新对象提交给数据库之前,FK并不存在 - 但似乎有信息允许查找工作。以下面的代码为例。Linq-to-SQL:在提交事务之前无法访问外键

public Course Create(string name, int teacherID) 
{ 
    using (MyDataContext context = new MyDataContext()) 
    { 
     Course c = new Course(); 

     c.Name = name; 
     c.TeacherID = teacherID; //FK here, assume the value references a valid Teacher. 
     context.Courses.InsertOnSubmit(c); //c now has a context it can use. 

     //Try to do some validation here, before commiting the Course to the database. 
     //c.Teacher will be null here, leading to an exception. 
     if (c.Teacher.FirstName.Equals("Phil")) 
      throw new ApplicationException("Phil quit last year."); //Throwing here would cause the transaction to never commit, good. 

     context.SubmitChanges(); 

     //Email the teacher. 
     SendEmail(c.Teacher.EmailAddress); //c.Teacher is no longer null, this would work fine. 
    } 
} 

上面的代码有一些评论,应该说明我在问什么。我的问题基本上是这样的:

为什么我必须先为SubmitChanges查找基于已经设置在对象上的原始ID(FK)的值?

回答

4

是的,c.Teacher在那里为空。 Linq-To-Sql没有提供任何机制来加载基于手动填充的外键列的实体(至少,直到你到达SubmitChanges)。当然,如果你已经从数据库中提取实体,它会延迟加载 - 但是在这里你正在创建它。无论是通过在teacher实体(而不是ID)或手动获取的实体,并设置改为:

c.Teacher = teacher 

代替

c.TeacherID = teacherID 
+0

传递的实体就会变得混乱,如果它从同一个DataContext的不我希望不必每个** FK实体都预取**。但是,唉,我可能必须这样做。谢谢。 – 2011-06-07 23:14:12

+0

如果您确实需要从中获取数据,则只需预先获取它们即可。 (显然,在这种情况下,你是否可以问)为什么在调用另一个方法时涉及单独的datacontext?通常的模型是每个线程/请求/等的一个数据上下文。否则,您可以传入实体,但*仍*设置“EntityID”。只要确保你引用传入的参数,而不是实体属性。 – 2011-06-07 23:17:26

+0

问题的真正原因在于,如果您为每个根据传入参数设置属性的实体都有一个create方法,然后在*之前调用一些'Validate(theObject)'方法对其属性**进行验证, *将其提交给数据库。这就是为什么我说“预取每个FK”,因为你不知道“Validate”方法需要检查哪些。 – 2011-06-07 23:26:49