在实体框架中创建双链表 [英] Creating a double linked list in Entity Framework

查看:135
本文介绍了在实体框架中创建双链表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个对象可以选择地引用下一个和/或上一个记录。这样的东西:

  public class Foo 
{
[Key]
public int Id {得到; set;}

[ForeignKey(上一个)]
public int? PreviousId {get; set;}

public Foo上一个{get; set;}

[InverseProperty(Previous)]
public Foo Next {get; set;}
}

不幸的是,这不起作用,而是导致错误消息无法确定类型Foo和Foo之间的关联的主体结束



想法是通过设置 PreviousId ,上一个 Foo 将通过EF自动设置其下一个。这是为了防止由下一个上一个失去同步的错误。还要注意, PreviousId 可以是 null ,在这种情况下,数据库中的记录不应该有一个下一个指向该记录。有什么办法实现吗?

解决方案

我通过流畅的api aproach实现了你想要的。我需要从Foo类中删除PreiousId属性 - 它将通过映射添加。

  public class Foo 
{
[Key]
public virtual int Id {get;组; }

public virtual Foo上一个{get;组; }

public virtual Foo Next {get;组; }
}

将所有属性更改为虚拟,这将允许ef动态跟踪状态的内存中的属性。然后在DbContext派生类里面,你需要重写OnModelCreating方法并在其中定义映射:

  protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity< Foo>()
.HasOptional(f => f.Next)
.WithOptionalPrincipal(f => f.Previous)
。 Map(c => c.MapKey(PreviousId));

base.OnModelCreating(modelBuilder);
}

这将添加到Foo表PreviousId列,这将是外键关系。它将定义1-0关系。如果您将一个Foo实体分配给另一个上一个属性,则分配的实体将在Next属性中引用它。我使用以下代码测试了它:

  using(MyDbContext context = new MyDbContext(Test))
{
context.Database.Delete();
Foo foo1 = context.Foos.Create();
Foo foo2 = context.Foos.Create();
foo1.Next = foo2;
context.Foos.Add(foo1);
context.Foos.Add(foo2);
context.SaveChanges();
}
using(MyDbContext context = new MyDbContext(Test))
{
Foo foo1 = context.Foos.OrderBy(f => f.Id).First ();
Foo foo2 = context.Foos.OrderBy(f => f.Id).Skip(1).First();
// foo1.Next == foo2和foo2.Previous == foo1
}


I have an object which can optionally have a reference to a next and/or previous record. Something like this:

public class Foo
{
  [Key]
  public int Id {get; set;}

  [ForeignKey("Previous")]
  public int? PreviousId {get; set;}

  public Foo Previous {get; set;}

  [InverseProperty("Previous")]
  public Foo Next {get; set;}
}

Unfortunately this does not work, instead resulting in the error message Unable to determine the principal end of an association between the types Foo and Foo.

The idea is that by setting the PreviousId, the Previous Foo will get its Next set automatically by EF. This is to prevent errors caused by Next and Previous getting out of sync. Also note that PreviousId can be null, in which case no record in the database should have a Next pointing at that record. Is there any way to implement this?

解决方案

I've managed to achieve what you wanted by using fluent api aproach. I needed to remove PreiousId property from Foo class - it will be added later on by mapping.

public class Foo
{
    [Key]
    public virtual int Id { get; set; }

    public virtual Foo Previous { get; set; }

    public virtual Foo Next { get; set; }
}

Change as well all your properties to virtual as this will allow ef to dynamically track state of the properties in the memory. Then inside DbContext derived class you need to override OnModelCreating method and define mapping there:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Foo>()
        .HasOptional(f => f.Next)
        .WithOptionalPrincipal(f => f.Previous)
        .Map(c => c.MapKey("PreviousId"));

    base.OnModelCreating(modelBuilder);
}

This will add to Foo table PreviousId column which will be the foreign key of the relationship. It will define 1-0 relationship. If you assign one Foo entity to another's Previous property then assigned entity will have reference to it in Next property. I tested it with the following code:

using(MyDbContext context = new MyDbContext("Test"))
{
    context.Database.Delete();
    Foo foo1 = context.Foos.Create();
    Foo foo2 = context.Foos.Create();
    foo1.Next = foo2;
    context.Foos.Add(foo1);
    context.Foos.Add(foo2);
    context.SaveChanges();
}
using (MyDbContext context = new MyDbContext("Test"))
{
    Foo foo1 = context.Foos.OrderBy(f => f.Id).First();
    Foo foo2 = context.Foos.OrderBy(f => f.Id).Skip(1).First();
    // foo1.Next == foo2 and foo2.Previous == foo1
}

这篇关于在实体框架中创建双链表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆