我正在使用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映射...
答案 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; }
}