重用继承的FK-Relationship?

时间:2013-09-04 14:21:32

标签: c# entity-framework ef-code-first ef-migrations

我正在使用C#/。net 4.5和EF 6创建一个应用程序,并想知道我是否能以某种方式执行以下操作:

我有两个基类,如:

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

    public List<BaseRevision> Revisions { get; set; }
}

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

    public BaseItem Item { get; set; }
}

现在我将它们推导出来,如下所示:

[Table("ContentItems")]
public class ContentItem : BaseItem
{
    public string ContentType { get; set; }
}

[Table("ContentRevisions")]
public class ContentRevision : BaseRevision
{
    public string Text { get; set; }
}

这很好用,EF甚至处理如下查询:

var revisions = db.ContentItems.Where(i => i.Revisions.Any(r => (r as ContentRevision).Text.Contians("ABC")));

这正如我所期望的那样转换为SQL,但我想“摆脱as”(在其他一些情况下会导致更多复杂化)。

我尝试为BaseItem使用泛型,但EF不支持这样做,所以我尝试了以下内容:

[Table("ContentItems")]
public class ContentItem : BaseItem
{
    public string ContentType { get; set; }

    public List<ContentRevision> ContentRevisions { get; set; }
}

[Table("ContentRevisions")]
public class ContentRevision : BaseRevision
{
    public string Text { get; set; }

    public ContentItem ContentItem { get; set; }
}

所以我可以使用上面的查询:

var revisions = db.ContentItems.Where(i => i.ContentRevisions.Any(r => r.Text.Contians("ABC")));

但是我无法使用“BaseItems”表中继承的外键“Item_Id”来使用它。 EF总是希望使用“ContentItems”表中的新“ContentItem_Id”键创建第二个FK-Relation,这将复制关系(并可能导致其他一些副作用)。

这在某种程度上是可能的(或者有更好的想法来解决/改善这个问题/模式)?

更新:可以下载演示项目HERE。如果添加新的迁移,它将创建我不想要的第二个FK映射...

3 个答案:

答案 0 :(得分:1)

编辑:

你不需要在这里添加复杂的关系,这正是OfType&lt;&gt;用于。

如果只想访问ContentItems,请在继承对象中创建新列表,使用BaseItem列表并写入:

(i is a BaseItem)
i.Revison.OfType<ContentItem>

您将使用此常用列表存储所有不同的BaseItems。 由于编译器,它的开发者没有错误,因为当使用OfType&lt;&gt;时func,你只能得到你想要的打字对象。

初步答案: 如果您的初始问题是所有修订都不是ContentRevision,并且导致您的查询在as转换时失败,那么您应该这样写:

var revisions = db.ContentItems.Where(i => i.Revisions.OfType<ContentRevision>.Any(r => r.Text.Contains("ABC")));

答案 1 :(得分:0)

您是否尝试过使用ForeignKey数据注释来告诉实体框架哪些属性用于外键。即。

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

  public List<BaseRevision> Revisions { get; set; }
}

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

  [ForeignKey("Id")]
  public BaseItem Item { get; set; }
}

[Table("ContentItems")]
public class ContentItem : BaseItem
{
    public string ContentType { get; set; }
}

[Table("ContentRevisions")]
public class ContentRevision : BaseRevision
{
  public string Text { get; set; }
}

或使用Fluent API指定关系,即BaseItem类

modelBuilder.Entity<BaseItem>()
.HasMany(t => t.Revisions)
.WithRequired(t => t.Item)
.HasForeignKey(t => t.Id);

答案 2 :(得分:0)

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

   public List<BaseRevision> Revisions { get; set; }
  }

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

    public Int BaseItemID{get;set;}
    [ForeignKey("BaseItemID")]
     public BaseItem Item { get; set; }
  }