[images&从处理XAML&的另一个线程中获取的代码树视图数据here]
专家,
摘要
我使用EF& amp;创建一个2个或更多分层对象Code First,数据库创建所有外键和&奇妙地填补他们。但是因为我无法在代码中看到这些键,所以我无法找到一种方法来创建返回父级,子级,该子级等的LINQ查询。
简易结构
Access_Group - > Access_List - > Object_Group - > ...... (但示例/校样只需要2个级别)
首先,这是用于创建最高'父级'项目的 top 级别类:
Public Class Access_Group
Inherits EntityTypeConfiguration(Of Access_Group)
Implements IAccess_Group
<Key>
Public Property Access_GroupID As Integer Implements IAccess_Group.Access_GroupID
Public Property Name As String Implements IAccess_Group.Name
Public Property LastUpdated As Date Implements IAccess_Group.LastUpdated
Public Property Active As Boolean Implements IAccess_Group.Active
'------------------------------------------------------------------
Public Property Access_Lists As ObservableCollection(Of Access_List) Implements IAccess_Group.Access_Lists
Public Sub New()
Me.Access_Lists = New ObservableCollection(Of Access_List)
End Sub
End Class
正如您所看到的,我使用ObservableCollection创建一个子/子...当我这样做并且 Add-Migration Foo 时,VS2012中的EF6会创建您期望的内容:
......并且在资源管理器中:
...在典型的,可接受的EF样式中,外键列在MSSQL2012中自动创建为:
大!
现在上面我没有手动创建关系,就是......我这样做了:
Private Sub AddData()
Try
ctx = New entitiesContext
Dim d As Date = Now
'--------------------------------
Dim al As New Access_List
' lower classes not needed to be shown...
With al
.Active = True
.Checked = True
.LastUpdated = d
.Name = "some access-list at " & d.ToLongTimeString
End With
'--------------------------------
Dim ag As Access_Group = New Access_Group
With ag
.Access_Lists.Add(al)
.Active = True
.LastUpdated = d
.Name = "some access-group at " & d.ToLongTimeString
End With
'
ctx.Access_Groups.Add(ag)
'
Dim i As Integer = ctx.SaveChanges()
Console.WriteLine("Seed complete! -> " & i)
Catch ex As Exception
Dim exText As String = "Seed Failed "
Console.WriteLine(exText & "(Message): " & ex.Message)
Console.WriteLine(exText & "(ToString): " & ex.ToString)
Console.WriteLine(exText & "(StackTrace): " & ex.StackTrace)
Console.WriteLine("EntityValidationErrors: ")
For Each eve As System.Data.Entity.Validation.DbEntityValidationResult In ctx.GetValidationErrors()
Console.WriteLine("eve: OK? " & eve.IsValid & " - " & eve.Entry.ToString)
For Each devr As System.Data.Entity.Validation.DbValidationError In eve.ValidationErrors
Console.WriteLine("devr invalid property: " & devr.PropertyName)
Console.WriteLine("devr error message : " & devr.ErrorMessage)
Next
Next
End Try
End Sub
所以你看,我用(顶级):
ctx.Access_Groups.Add(AG)
...添加Access_Group类,但只有在将与之关联/相关的Access_List类添加为:
之后With ag
.Access_Lists.Add(al)
...当然,我们的Access_List类拥有它自己的子节点,因为之前添加了Object_Groups:
With al
.Object_Groups.Add(og)
......等等。基本上,每个子ID都添加到父级,最后通过我们的DBContext添加顶级父级。
问题/证据
完成这样的LINQ查询后:
Dim ags = From ag In ctx.Access_Groups Select ag
我完全期望不仅仅是顶级课程,但如果我挖到每个课程,我也会得到他们的孩子,孙子等等。
事实并非如此!
简单的证明/调试Sub liek如下:
Public Sub PrintDebug(TheList As IEnumerable(Of Access_Group))
For Each ag As Access_Group In TheList
Console.WriteLine("=======================================")
Console.WriteLine("ag: " & ag.Name & " has " & ag.Access_Lists.Count & " Access_List entries")
For Each al As Access_List In ag.Access_Lists
Console.WriteLine("ag -> al: " & al.Name & " has " & al.Object_Groups.Count & " Object_Group entries")
For Each og As Object_Group In al.Object_Groups
Console.WriteLine("ag -> al -> og: " & og.Name & " has " & og.Network_Objects.Count & " Network_Object entries")
'...
Next
Next
Console.WriteLine("=======================================")
Next
End Sub
...让我认为(愚蠢/无知)成为一个惊喜:
=======================================
ag: some access-group at 5:00:49 PM has 0 Access_List entries
=======================================
=======================================
ag: some access-group at 5:08:56 PM has 0 Access_List entries
=======================================
=======================================
ag: some access-group at 5:09:14 PM has 0 Access_List entries
=======================================
=======================================
ag: some access-group at 5:12:31 PM has 0 Access_List entries
=======================================
[...]
WTF?
在POCO中,您可以获得整个班级 - 包括该实例的所有孩子。但是在EF(我正在这样做的方式)中,耦合是松散的。
需要
不知何故,我需要为数据库中的那些顶级项目执行LINQ查询,并且自动让数据库中与之关联的所有子项都与之相关。
但是因为代码/业务逻辑不能看到FK,所以我不能简单地测试密钥之间的相等性......
如何比我更聪明的人对这样的等级关系进行LINQ查询&amp;得到所有的好东西?
不想要
最优雅的方式通常是最好的...
你有什么想法?
TIA!
答案 0 :(得分:0)
专家,
通过坚持不懈,坚持不懈和盲目运气,我想我发现了这个问题 - 或者至少是一个原因......
简短版本:我必须查找原因,但在CF EF6中,我无意中未启用“模型中的外键列”,如:
但是 ...我使用 Code First ,而不是数据库优先 ...我只是包含上面的图片所以你能理解我所说的方面。 :)
鉴于上面的PrintDebug()子,以下查询:
Dim agList As List(Of Access_Group) = _
(From ag In ctx.Access_Groups.Include("Access_Lists") Select ag).ToList
Me.AccessGroups = New ObservableCollection(Of Access_Group)(agList)
Me.PrintDebug(Me.AccessGroups)
...产生以下结果(与上面的/ OP相比):
[...]
=======================================
ag: some access-group at 5:00:49 PM has 1 Access_List entries
ag -> al: some access-list at 5:00:49 PM has 0 Object_Group entries
=======================================
=======================================
ag: some access-group at 5:08:56 PM has 1 Access_List entries
ag -> al: some access-list at 5:08:56 PM has 0 Object_Group entries
=======================================
=======================================
ag: some access-group at 5:09:14 PM has 1 Access_List entries
ag -> al: some access-list at 5:09:14 PM has 0 Object_Group entries
=======================================
=======================================
ag: some access-group at 5:12:31 PM has 1 Access_List entries
ag -> al: some access-list at 5:12:31 PM has 0 Object_Group entries
=======================================
[...]
因此查询中的操作差异是:
ctx.Access_Groups.**Include**("Access_Lists") Select ag
......现在在Lerman&amp; amp;当我创建类时,Miller将在Code First中找到我/我应该如何做到这一点(或者如果我很幸运,如何添加 - 迁移/更新 - 数据库并且 in situ ! )
仍然欢迎任何输入!
感谢您的考虑!
P.S。堆栈丢失了我的原始帐户,我不得不重新开始(多年后),所以现在我甚至无法编辑,评论或更新我的帖子或评论......呃......我会尝试用CF更新将FK作为列启用的方法... 如果我可以 :(