【问题标题】:EntityFramework using with database foreign keyEntityFramework 与数据库外键一起使用
【发布时间】:2012-09-28 00:54:46
【问题描述】:

实际上我花了一整天的时间在外键的 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”。 1 'LookupProcess' 是预期的。

我能问一下插入错误吗?我的查询是否正确?

【问题讨论】:

  • 对于第二部分,是否真的有一个从 LookupProcess 返回的实例?
  • 实例返回是什么意思?
  • 数据库中是否真的有该描述的记录?

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


【解决方案1】:

第一个问题:

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

【讨论】:

  • 其实我之前试过这个,它说NULL指针....是那个版本的EF问题吗?
  • 如果可行,我可以使用 p.LookupProcess.descr = "example" 作为插入方式
【解决方案2】:

实际上,您错过了 DataEntityModel 及其框架中的一些概念。要操作数据,您必须从上下文的角度调用对象。这些允许您向 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()

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

【讨论】:

  • 你不能只添加而不是附加并将状态更改为已添加吗?
  • 不推荐,尤其是当您使用引用或其他任何方式操作数据时。
  • Attach 假定实体已经在数据库中。此外,如果您将状态更改为已添加,我相信 EF 不会看到任何差异。显然,如果您知道密钥并且数据库生成密钥,那么您想使用 Attach 但是如果您自己设置密钥,那么我相信 Add 是正确的做法。就相关实体而言 - Attach 和 Add 都不理想。 Attach 将附加实体和所有相关实体(因此它将假定它们都在数据库中),而 Add 将添加实体和所有相关实体(因此它将假定它们都不在数据库中)
【解决方案3】:

对于您的第一个问题,扩展 @jeroenh 的建议:

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

添加Include 语句将水合LookupProcess 实体,以便您可以查询它们。如果没有Includex.LookupProcess 将为空,这很可能解释了您遇到错误的原因。

如果使用文字字符串作为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

引用类型和可空类型的默认值为 null。

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

“AmpCUEngEntities.Processes”中的实体参与“FK_Process_LookupProcess”关系。找到 0 个相关的“LookupProcess”。 1 'LookupProcess' 是预期的。

为避免此类问题,您需要在 p.LookupProcess 进入数据库之前检查它是否不为空。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-03
    • 1970-01-01
    • 1970-01-01
    • 2016-11-13
    • 1970-01-01
    • 2016-05-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多