因为这是一个非常奇特的情况,所以没有支持它的构建。但是你可以让它看起来不错。
现在,假设您的连接表称为 E1E2,您就有了类似的东西。
public partial class E1
{
public Guid Id { get; set; }
public IQueryable<E1E2> Stack { get; }
}
public partial class E2
{
public Guid Id { get; set; }
public IQueryable<E1E2> In { get; }
}
public partial class E1E2
{
public E1 E1 { get; set; }
public E2 E2 { get; set; }
public Int32 Position { get; set; }
}
作为 hoc,我无法想出更好的解决方案来将其映射到数据库。为了使使用尽可能智能,只需向实体添加一些属性和方法。这很容易,因为实体 a 生成为部分类。
使用以下内容扩展 E1 类。
public partial class E1
{
public IQueryable<E2> NiceStack
{
get { return this.Stack.Select(s => s.E2).OrderBy(s => s.Position); }
}
public void Push(E2 e2)
{
this.Stack.Add(
new E1E2
{
E2 = e2,
Position = this.Stack.Max(s => s.Position) + 1
});
}
public E2 Pop()
{
return this.Stack.
Where(s => s.Position == this.Stack.Max(s => s.Position).
Select(s => s.E2).
Single();
}
}
使用以下内容扩展 E2 类。
public partial class E2
{
public IQueryable<E1> NiceIn
{
get { return this.In.Select(i => i.E1); }
}
public IQueryable<E1> NiceTop
{
get
{
return this.In.
Where(i => i.Position == i.E1.Stack.Max(s => s.Position)).
Select(i => i.E1);
}
}
}
到此为止。现在应该可以围绕这些实体编写相当不错的代码了。代码中可能存在一些错误,但想法应该很清楚。我省略了代码以确保在访问时加载相关属性。您可以进一步将原始属性设为私有并将它们隐藏起来。也许您不应该包含 NiceStack 属性,因为它允许随机访问。或者,也许您想添加更多扩展 - 也许让 NiceTop 可写,将 E2 实例推送到插入到 E2 实例的 NiceTop 中的 E1 实例的堆栈上。但这个想法保持不变。
对 Single() 的调用不适用于普通的实体框架;而是使用 ToList().Single() 切换到 LINQ to Object 或使用 First() 但 first() 不保留确切的语义。