【问题标题】:Linq-to-SQL: foreign key not accessible until transaction is committedLinq-to-SQL:在提交事务之前无法访问外键
【发布时间】:2011-06-07 22:46:06
【问题描述】:

我发现使用 Linq-to-SQL,当您创建新对象时,您无法访问外键成员,直到您在“创建新对象”的上下文中调用 SubmitChanges。当然,我知道在您将新对象提交到数据库之前,FK 并不真正存在 - 但似乎信息在那里允许查找工作。以下面的代码为例。

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.
    }
}

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

为什么我必须首先 SubmitChanges 才能根据已在对象上设置的原始 ID (FK) 查找值?

【问题讨论】:

    标签: c# .net linq-to-sql datacontext


    【解决方案1】:

    是的,c.Teacher 在那里为空。 Linq-To-Sql 不提供任何机制来基于手动填充的外键列加载实体(至少,直到您到达SubmitChanges)。如果您从数据库中提取实体,它肯定会延迟加载——但在这里您正在创建它。要么传入 teacher 实体(而不是 id),要么手动获取实体并设置它:

    c.Teacher = teacher
    

    而不是

    c.TeacherID = teacherID
    

    【讨论】:

    • 如果实体不是来自同一个 DataContext,那么传入实体会变得混乱,我希望不必预取 每个 FK 实体。但是,唉,我可能不得不这样做。谢谢。
    • 只有在您确实需要从中获取数据时,您才需要预先获取它们。 (在这种情况下,您显然是)请问为什么在从另一种方法调用一种方法时涉及单独的数据上下文?通常的模型是每个线程/请求/等一个数据上下文。否则,您可以传入实体,但仍然设置EntityID。只需确保引用传入的参数,而不是实体属性。
    • 问题的真正原因是您是否为每个实体创建了一个方法,该方法根据传入的参数设置属性,然后调用一些Validate(theObject) 方法对其属性进行一些验证将其提交到数据库之前。这就是我说“预取每个 FK”的原因,因为您不知道 Validate 方法需要检查哪些。
    • 而且DataContext不止一个的原因是多线程/并行处理。我确实更喜欢传递实体而不是继续获取​​它们,但正如我所提到的,使用多个 DataContext 可能会变得混乱。
    • @Josh,我明白你在说什么。你想让.InsertSubmitChanges 所做的事情——同步实体。但它并没有这样做,不幸的是,您对此无能为力。原则上,如果您自己(通过代码生成)生成实体,您可以想象修改 ID 属性的设置器,以便它们还将基础 EntityRefsource 属性设置为您的 IQueryable “预取”它。而且由于它是IQueryable,它会尊重延迟加载,因此如果它没有被访问,就不会真正获取它。不过,这不是微不足道的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-19
    • 2014-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多