我正在学习使用C#POCO在版本6+上首先使用代码的实体框架(EF)。请考虑以下示例:
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
,运行不必要的查询。
是否有更好的替代方法来做我想要的:将子实体添加到现有父级?
更新
根据cverb的回答,我得到了以下代码,按照我的意愿行事:
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”代码来改变Context。这明确定义了类中属性之间的关系。
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; }
}
这使我能够成功应用迁移。
答案 0 :(得分:2)
您应该在ParentId
实体上明确添加TextElement
。
public int? ParentId { get; set; }
如果您不知道如何做到这一点,请在this page下的“了解一对多关系惯例”一节中提供一些很好的信息。
然后您只需使用以下代码即可添加新实体。
using (var context = new DatabaseContext())
{
var child = new TextElement { Content = "I iz kiddo", ParentId = 42 };
context.SaveChanges();
}
无需将子项附加或添加到父项Children
- 列表中,因为实体框架将自行获取更改。
答案 1 :(得分:0)
您正在使用的方式是正确的方式......在这里,EF上下文为您完成所有工作:启动事务执行插入所需的编辑和删除,最后提交更改。
答案 2 :(得分:0)
继续这个
我想要做的是将新子项添加到现有父级
和你使用的这个sql脚本
INSERT INTO Textuals(Content,ParentId)VALUES(&#34; Lorem Ipsum&#34;,42)
这是适合你的。
using (var context = new DatabaseContext())
{
var newTextual = new Textuals { Number = 42, Content = "I iz kiddo" };
context.Textuals.Attach(newTextual);
context.SaveChanges();
}