2011-04-23 72 views
3

我爲我的下一個項目使用Code First。我非常喜歡這個想法,迄今爲止它的運作非常好。我唯一的牛肉是,我找不到任何關於如何使用這個野獸的文檔,而谷歌搜索通常指的是現在過時的CTP。從POCO對象引用DbContext

對於這個問題,我將模擬一個有向圖。 圖遍歷的算法不是最佳的。

我有一個簡單的POCO結構,這樣

class Graph : DbContext 
{ 
    public DbSet<Node> Nodes { get; set; } 
    public DbSet<Edge> Edges { get; set; } 

    public Graph(string connectionString) : base(connectionString) { } 
} 

class Edge 
{ 
    public int Id { get; set;} 
    public double Weight { get; set; } 

    public Node StartNode { get; set; } 
    public Node EndNode { get; set; } 
} 

class Node 
{ 
    public int Id { get; set; } 
    public string Label { get; set; } 
} 

簡潔明快的東西。

但是現在假設我想向每個節點添加對Graph對象的某種引用,以便節點可以在圖的上下文中找出有關它自身的信息,例如它有多少條邊。

我希望我的節點,創建時,有

class Node 
{ 
    public int Id { get; set; } 
    public string Label { get; set; } 

    //I want this property populated by magic. 
    //Just leaving it here crashes the program 
    public Graph Graph { get; set; } 

    //So that this property would do meaningful things. 
    public int EdgesFromThisNode 
    { 
     get { return Graph.Edges.Count(e => e.StartNode.Id == Id); } 
    } 
} 

我認爲我走出會議在這裏解決這個我有一個特別的問題。例如,該屬性可以作爲方法移動到Graph類。我不想這樣做的原因是因爲我想綁定到這個屬性,綁定是邪惡的。

你們其中的一個嚮導能夠指導我將註釋/實體類型配置魔術的正確組合拉到這個快速的一個嗎?

是否有我應該注意的不同約定?例如,如果我以某種方式可以綁定所有的邊或者更好,那麼一些邊(從節點發出的邊)到達Node,那就更加優雅了。

在此先感謝您,如果您有任何Code First發燒友應該閱讀的建議......首先,請分享您的鏈接!

回答

4

您可以引入關聯的另一端,即從節點開始並以節點結束的邊的集合。

modelBuilder.Entity<Edge>() 
      .HasRequired(e => e.StartNode) 
      .WithMany(n => n.OutgoingEdges); 

modelBuilder.Entity<Edge>() 
      .HasRequired(e => e.EndNode) 
      .WithMany(n => n.IncomingEdges); 

當加載Node:你不會需要那麼在Node類數據庫上下文:在流利配置

class Edge 
{ 
    public int Id { get; set;} 
    public double Weight { get; set; } 

    [InverseProperty("OutgoingEdges")] 
    [Required] 
    public Node StartNode { get; set; } 
    [InverseProperty("IncomingEdges")] 
    [Required] 
    public Node EndNode { get; set; } 
} 

class Node 
{ 
    public int Id { get; set; } 
    public string Label { get; set; } 

    public ICollection<Edge> OutgoingEdges { get; set; } 
    public ICollection<Edge> IncomingEdges { get; set; } 

    public int EdgesFromThisNode 
    { 
     get { return OutgoingEdges != null ? OutgoingEdges.Count() : 0; } 
    } 
} 

或者,如果你不想在Edge類的屬性你必須確保你想要加載的邊緣的集合:

using (var graph = new Graph()) 
{ 
    Node node = graph.Nodes.Include(n => n.OutgoingEdges) 
        .FirstOrDefault(n => n.Id == 1); 
    // node.EdgesFromThisNode would give now correct result 
} 

另外,你可以標記你的導航屬性ies作爲virtual受益於延遲加載。

注意:此解決方案僅在您對節點的傳出和傳入邊緣感興趣時纔有用。 (我主要是指你的問題的這一部分:「如果我以某種方式可以綁定所有邊緣或更好,一些邊緣(從節點發出的邊緣)到節點...」)如果你只想請從數據庫(所有Edge對象)中加載太多邊緣的

編輯

一些資源約EF 4.1,尤其是代碼優先:

代碼優先演練:關於EF 4.1 http://blogs.msdn.com/b/adonet/archive/2011/03/15/ef-4-1-code-first-walkthrough.aspx

12部分教程:http://blogs.msdn.com/b/adonet/archive/2011/01/27/using-dbcontext-in-ef-feature-ctp5-part-1-introduction-and-model.aspx

Morteza Manavi關於Code-First中關聯和繼承的博客:http://weblogs.asp.net/manavi/default.aspx

關於EF 4.1 MSDN網頁:http://msdn.microsoft.com/en-us/library/gg696172%28v=vs.103%29.aspx

一些視頻教程:http://msdn.microsoft.com/en-us/data/cc300162

編輯2

如果你想邊的只綁定到一個視圖,而不加載所有我會考慮使用ViewModel來處理節點本身,並且具有附加屬性:

public class NodeViewModel 
{ 
    public Node Node { get; set; } 
    public int NumberOfOutgoingEdges { get; set; } 
} 

我會留在Node類的兩個導航集合(和刪除EdgesFromThisNode屬性),但我不會加載收藏此特異性結合場景,改用投影到新視圖模型類型:

using (var graph = new Graph()) 
{ 
    NodeViewModel nodeViewModel = graph.Nodes 
     .Where(n => n.Id == 1) 
     .Select(n => new NodeViewModel() 
      { 
       Node = n, 
       NumberOfOutgoingEdges = n.OutgoingEdges.Count() 
      }) 
     .FirstOrDefault(); 
    // nodeViewModel.Node doesn't have the OutgoingEdges loaded now 
} 

然後您將NodeViewModel綁定到您的視圖,而不是直接綁定Node。這個解決方案避免了以某種方式將數據庫上下文注入到模型類中(這與我認爲的POCO的想法非常相反)。

+0

謝謝你提供一個非常全面的答案,我將回顧我的實際問題以及這個解決方案如何適應它。你知道是否可以將Graph對象引用附加到每個節點?它味道不好嗎? – Gleno 2011-04-23 19:17:48

+0

那個12段教程真的很棒的人! – Gleno 2011-04-23 19:36:45

+0

@格萊諾:對我來說,它的味道不好,是的。 「POCO」的想法是在其中沒有持久性相關代碼或參考。我在我的答案中附加了Edit2部分,作爲您的綁定方案的替代解決方案,避免在模型類中具有上下文。我不知道這是否會滿足您的所有要求。 – Slauma 2011-04-23 20:09:12