实体框架 - 两个导航属性,一键?

时间:2013-12-13 16:06:21

标签: c# entity-framework

我花了几个小时尝试谷歌答案,但我什么都没有。我希望只是因为我不知道如何用这句话而不是技术限制。

我正在使用Entity Framework Code-First(v5),我正在尝试创建一个共享一个外键的两个导航属性的模型。显然,这个外键在数据库中不存在,因为它无法指向两个子表。 EF能够解决这个问题并且仍然使用自定义映射或注释找出我想要的东西吗?

示例:

public class Parent {
  public int Id { get; set; }
  public string EntityType { get; set; }
  public int EntityId { get; set; }
  // Additional properties

  [SomeSortOfAttributeICanPutHereToIndicateThisShouldUse("EntityId")] //?
  public virtual Child1 { get; }
  [SomeSortOfAttributeICanPutHereToIndicateThisShouldUse("EntityId")] //?
  public virtual Child2 { get; }
}

public class Child1 {
  public int Id { get; set; }
  public string Prop1 { get; set; }
}

public class Child2 {
  public int Id { get; set; }
  public string Prop2 { get; set; }
}

public Database : DbContext {
  public DbSet<Parent> Parents { get; set; }
  public DbSet<Child1> Children1 { get; set; }
  public DbSet<Child2> Children2 { get; set; }
}

var db = new Database();
var child1prop = db.Parents.First(p => p.EntityType == "Child1").Child1.Prop1;
var child2prop = db.Parents.First(p => p.EntityType == "Child2").Child2.Prop2;

我正在尝试使用Entity Framework做什么,或者我是在浪费时间?

2 个答案:

答案 0 :(得分:0)

我认为处理这个问题的更好方法是在Parent实体上设置一个子集合?这是一个简单的1对多关系。

父类将包含一个子集合,子节点将引用其父节点,然后父节点可以有x个子节点而不是两个子节点。

public class Parent {
  public int Id { get; set; }
  // Additional properties

  public virtual List<Child> Children { get; set; }
}

public class Child {
  public int Id { get; set; }
  public string Prop1 { get; set; }

  public int ParentId { get; set; }
  public Parent Parent { get; set; }
}

public Database : DbContext {
  public DbSet<Parent> Parents { get; set; }
  public DbSet<Child> Children { get; set; }
}

答案 1 :(得分:0)

我认为这是不可能的。这听起来像是尝试从parent.cid到child1.cid以及从parent.cid到child2.cid设置为FK约束。

我只是测试:这似乎有可能(?!!#!):

CREATE TABLE [dbo].[parent](
    [pid] [int] NOT NULL,
    [cid] [int] NULL,
 CONSTRAINT [PK_parent] PRIMARY KEY CLUSTERED 
(
    [pid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

ALTER TABLE [dbo].[parent]  WITH CHECK ADD  CONSTRAINT [FK_parent_child1] FOREIGN KEY([cid])
REFERENCES [dbo].[child1] ([cid])
GO

ALTER TABLE [dbo].[parent] CHECK CONSTRAINT [FK_parent_child1]
GO

ALTER TABLE [dbo].[parent]  WITH CHECK ADD  CONSTRAINT [FK_parent_child2] FOREIGN KEY([cid])
REFERENCES [dbo].[child2] ([cid])
GO

ALTER TABLE [dbo].[parent] CHECK CONSTRAINT [FK_parent_child2]
GO

<强> BUT:

这意味着当您将值设置为parent.cid时,您必须在child1和child2中都有一行。

Imho,这会导致精神分裂症。

面对同样的问题,我辞职了两个FK。

另一种选择是继承:

class base {
    int id {get; set;}
}

class child1 : base {
}

class child2 : base {
}

然后配置TPT。这将导致child1和child2的三个表。

在您的父级中,您可以拥有类型为base的属性。然后由你来处理这个属性作为child1或child2。

希望这会有所帮助