【发布时间】:2015-08-19 15:18:51
【问题描述】:
我正在学习实体框架 (EF),首先在版本 6+ 上使用代码和 C# POCO。考虑以下示例:
public class DatabaseContext : DbContext
{
public virtual DbSet<TextElement> Textuals { get; set; }
}
public class TextElement
{
[Key]
public int Number { get; set; }
public string Content { get; set; }
public virtual ICollection<TextElement> Children { get; set; }
}
我想要做的是将一个新的孩子添加到现有的父母。在伪 SQL 中,我可以执行以下操作:
INSERT INTO Textuals (Content, ParentId) VALUES ("Lorem Ipsum", 42)
其中 42 是父记录的 ID。
过去一天我一直在网上搜索让 EF 在 C# 代码中为我做同样的事情。我能找到的最好的是:
using (var context = new DatabaseContext())
{
var parent = new TextElement { Number = 42, Children = new List<TextElement>() };
var child = new TextElement { Content = "I iz kiddo" };
context.Textuals.Attach(parent);
parent.Children.Add(child);
context.SaveChanges();
}
不过,Attach 调用似乎也在运行查询。同样的问题也适用于按 id 删除实体,它也需要 Attach,运行不必要的查询。
是否有更好的替代方法来做我想做的事:将子实体添加到现有父实体?
更新
根据 cvverb 的回答,我得到以下代码做我想做的事:
public class TextElement
{
[Key]
public int Number { get; set; }
public string Content { get; set; }
public virtual ICollection<TextElement> Children { get; set; }
// Added custom parent id reference, MUST be nullable to allow
// for entries without parent
public int? ParentId { get; set; }
}
现在,因为这是一个打破惯例的名称(惯例规定 TextElementId 尽可能含糊不清),我需要用一点“流利的 api”代码来更改上下文。这明确定义了类中属性之间的关系。
public class DatabaseContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<TextElement>()
.HasMany((e) => e.Children) // Indicate the many relation
.WithOptional() // Indicate that the many
// relation is optional.
// Don't require a nav prop
.HasForeignKey((e) => e.ParentId); // The FK to use with the
// relation.
}
public virtual DbSet<TextElement> Textuals { get; set; }
}
这也使我能够成功应用迁移。
【问题讨论】:
-
您的 TextElement 实体中有
ParentIdproperty 吗? -
仅间接使用
Children属性。我显然喜欢 EF 来处理实现细节 =)。但如果可能的话,没有性能开销。
标签: c# entity-framework-6