保存相关数据

除了独立实体外,还可以利用模型中定义的关系。

小窍门

可以在 GitHub 上查看本文 的示例

添加新实体的图表

如果创建多个新的相关实体,将其中一个添加到上下文中会导致其他实体也被添加。

在以下示例中,博客和三篇相关文章都插入到数据库中。 找到并添加这些帖子,是因为它们可以通过 Blog.Posts 导航属性进行访问。

using (var context = new BloggingContext())
{
    var blog = new Blog
    {
        Url = "http://blogs.msdn.com/dotnet",
        Posts = new List<Post>
        {
            new Post { Title = "Intro to C#" },
            new Post { Title = "Intro to VB.NET" },
            new Post { Title = "Intro to F#" }
        }
    };

    context.Blogs.Add(blog);
    await context.SaveChangesAsync();
}

小窍门

使用 EntityEntry.State 属性仅设置单个实体的状态。 例如,context.Entry(blog).State = EntityState.Modified

如果从上下文已跟踪的实体的导航属性引用新实体,则会发现该实体并将其插入到数据库中。

在下面的示例中,由于从数据库中提取的 post 实体的 Posts 属性中添加了 blog,因此插入了该实体。

using (var context = new BloggingContext())
{
    var blog = await context.Blogs.Include(b => b.Posts).FirstAsync();
    var post = new Post { Title = "Intro to EF Core" };

    blog.Posts.Add(post);
    await context.SaveChangesAsync();
}

关系变化

如果更改实体的导航属性,则会对数据库中的外键列进行相应的更改。

在以下示例中,实体 post 将更新为属于新 blog 实体,因为它的 Blog 导航属性设置为指向 blog。 请注意,blog 也会插入到数据库中,因为它是一个新实体,并且被一个已经由上下文post跟踪的实体的导航属性所引用。

using (var context = new BloggingContext())
{
    var blog = new Blog { Url = "http://blogs.msdn.com/visualstudio" };
    var post = await context.Posts.FirstAsync();

    post.Blog = blog;
    await context.SaveChangesAsync();
}

删除关系

可以通过将引用导航 null设置为或从集合导航中删除相关实体来删除关系。

根据关系中配置的级联删除行为,删除关系可能会对依赖实体产生副作用。

默认情况下,对于必需的关系,将配置级联删除行为,并从数据库中删除子/从属实体。 对于可选关系,默认情况下不会配置级联删除,但外键属性将设置为 null。

请参阅 “必需”和“可选关系 ”,了解如何配置关系的必需性。

请参阅 Cascade Delete ,详细了解级联删除行为的工作原理、如何显式配置它们以及如何按约定选择它们。

在以下示例中,级联删除配置在BlogPost之间的关系上,因此post实体将从数据库中删除。

using (var context = new BloggingContext())
{
    var blog = await context.Blogs.Include(b => b.Posts).FirstAsync();
    var post = blog.Posts.First();

    blog.Posts.Remove(post);
    await context.SaveChangesAsync();
}