EntityFramework使用数据库外键

时间:2012-09-28 00:54:46

标签: asp.net vb.net entity-framework

实际上,我花了整整一天时间在外键的EntityFramework上。 假设我们有两张桌子。 过程(APP_ID,PROCESS_ID) LookupProcessId(process_id,process_description)

你可以理解两个带有名字的表,第一个表,使用process_id来表示每个应用程序,描述在seoncd表中。 其实我多次尝试并弄清楚如何做查询:它就像

Dim result = (from x in db.Processes where x.LookupProcess is (from m in db.LookupProcessIds where descr = "example" select m).FirstOrDefault() select x).FirstOrDefault()

首先,我想问一下是否有更简单的方法。

其次我想问的问题是关于插入

 p As New AmpApplication.CUEngData.Process
    p.app_id=100
    p.LookupProcess = (from m in db.LookupProcessIds where descr = "example" select m).FirstOrDefault()
 db.AddToProcesses(p)
 db.SaveChanges()

从外观看起来很好,但它给我错误说 'AmpCUEngEntities.Processes'中的实体参与'FK_Process_LookupProcess'关系。找到了0个相关的'LookupProcess'。预计会有'LookupProcess'。

我可以问是插错了吗?这是我的查询正确吗?

3 个答案:

答案 0 :(得分:0)

关于你的第一个问题:

 Dim result = (from x in db.Processes 
               where x.LookupProcess.descr = "example" 
               select x).FirstOrDefault()

答案 1 :(得分:0)

实际上,您错过了DataEntityModel及其Framework的一些概念。要操纵数据,您必须从上下文的角度调用对象。这些允许您向ObjectStateManager指定DataObject的状态。在您的情况下,如果您具有来自FK的依赖数据,则必须从叶到根添加/更新任何链接数据。

此示例演示了简单(无依赖)数据操作。选择是否存在以及插入或更新。

如果您想了解有关ObjectStateManager操作的更多信息,请转至http://msdn.microsoft.com/en-us/library/bb156104.aspx

    Dim context As New Processing_context 'deseign your context (this one is linked to a DB)

    Dim pro = (From r In context.PROCESS
                    Where r.LOOKUPPROCESS.descr = LookupProcess.descr
                    Select r).FirstOrDefault()

    If pro Is Nothing Then 'add a new one
        pro = New context.PROCESS With {.AP_ID = "id", .PROCESS_ID = "p_id"}

        context.PROCESS.Attach(pro)
        context.ObjectStateManager.ChangeObjectState(pro, System.Data.EntityState.Added)
    Else
        'update data attibutes
        pro.AP_ID = "id"
        pro.PROCESS_ID = "p_id"

        context.ObjectStateManager.ChangeObjectState(pro, System.Data.EntityState.Modified)
        'context.PROCESS.Attach(pro)
    End If

    context.SaveChanges()

我希望这会有所帮助。祝你有愉快的一天!

答案 2 :(得分:0)

关于你的第一个问题,要扩展@jeroenh的建议:

Dim result = (from x in db.Processes.Include("LookupProcess")  
    where x.LookupProcess.descr = "example"  
    select x).FirstOrDefault()

Include语句的添加将保留LookupProcess个实体,以便您可以查询它们。如果没有Includex.LookupProcess将为null,这可能会解释您为什么会遇到错误。

如果使用文字字符串作为Include的参数并不理想,请参阅Returning from a DbSet 3 tables without the error "cannot be inferred from the query"以获取使用嵌套实体执行此操作的示例。

关于你的第二个问题,这一行

p.LookupProcess = (from m in db.LookupProcessIds
    where descr = "example" select m).FirstOrDefault()

以后可能会导致您遇到问题,因为如果LookupProcessId没有process_description的“示例”,那么您将获得null。来自MSDN

  

reference和nullable类型的默认值为null。

因此,如果插入实体时p.LookupProcess为null,则会出现异常:

  

'AmpCUEngEntities.Processes'中的实体参与'FK_Process_LookupProcess'关系。找到了0个相关的'LookupProcess'。预计会有'LookupProcess'。

为了避免这种问题,您需要检查p.LookupProcess在进入数据库之前是否为空。

If Not p.LookupProcess Is Nothing Then 
    db.AddToProcesses(p)        
    db.SaveChanges()        
End If