2011-04-23 73 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