• Entity Framework Core系列教程-21-断开模式的实体图(Entity Graph)


    Entity Framework Core使用断开模式的实体图(Entity Graph)

    在上一章中,您学习了ChangeTracker如何自动更改所连接场景中每个实体的EntityState。在这里,您将了解Entity Framework Core中断开连接的实体图的根实体和子实体上不同方法的行为。
    实体框架核心提供了以下不同方法,这些方法不仅将实体附加到上下文,而且还更改了断开连接的实体图中每个实体的EntityState:

    • Attach()
    • Entry()
    • Add()
    • Update()
    • Remove()

    让我们看看以上方法如何更改Entity Framework Core 2.x中实体图中的每个实体的EntityState。

    Attach()

    DbContext.Attach()和DbSet.Attach()方法将附加指定的断开连接的实体图并开始对其进行跟踪。它们返回EntityEntry的实例,该实例用于分配适当的EntityState。

    下面的示例演示DbContext.Attach()方法在图形中每个实体的EntityState上的行为。

    public static void Main()
    {
        var stud = new Student() { //Root entity (empty key)
            Name = "Bill",
            Address = new StudentAddress()  //Child entity (with key value)
            {
                StudentAddressId = 1,
                City = "Seattle",
                Country = "USA"
            },
            StudentCourses = new List<StudentCourse>() {
                new StudentCourse(){  Course = new Course(){ CourseName = "Machine Language" } },//Child entity (empty key)
                new StudentCourse(){  Course = new Course(){  CourseId = 2 } } //Child entity (with key value)
            }
        };
    
        var context = new SchoolContext();
        context.Attach(stud).State = EntityState.Added;  
    
        DisplayStates(context.ChangeTracker.Entries());
    }
    
    private static void DisplayStates(IEnumerable<EntityEntry> entries)
    {
        foreach (var entry in entries)
        {
            Console.WriteLine($"Entity: {entry.Entity.GetType().Name},
                                 State: {entry.State.ToString()} ");
        }
    }
    Output:
    Entity: Student, State: Added
    Entity: StudentAddress, State: Unchanged
    Entity: StudentCourse, State: Added
    Entity: Course, State: Added
    Entity: StudentCourse, State: Added
    Entity: Course, State: Unchanged
    

    在上面的示例中,stud是学生实体图的实例,其中包括对StudentAddress和StudentCourse实体的引用。 context.Attach(stud).State = EntityState.Added会将图钉实体图附加到上下文,并为其设置Added状态。
    Attach()方法将添加的EntityState设置为根实体(在本例中为Student),无论其是否包含Key值。如果子实体包含键值,则它将被标记为“不变”,否则将被标记为“已添加”。上面示例的输出显示,学生实体具有Added EntityState,具有非空键值的子实体具有Unchanged EntityState,而具有空键值的子实体具有Added状态。
    下表列出了在为断开连接的实体图设置其他EntityState时,Attach(方法的行为。

    Attach() 具有键值的根实体 具有空值或CLR默认值的根实体 具有键值的子实体 空实体或CLR默认值的子实体
    context.Attach(entityGraph).State = EntityState.Added Added Added Unchanged Added
    context.Attach(entityGraph).State = EntityState.Modified Modified Exception Unchanged Added
    context.Attach(entityGraph).State = EntityState.Deleted Deleted Exception Unchanged Added

    ## Entry()

    与以前的EF 6.x相比,DbContext.Entry(方法在Entity Framework Core中的行为有所不同。考虑以下示例:

    var student = new Student() { //Root entity (empty key)
        Name = "Bill",
        Address = new StudentAddress()  //Child entity (with key value)
        {
            StudentAddressId = 1,
            City = "Seattle",
            Country = "USA"
        },
        StudentCourses = new List<StudentCourse>() {
                new StudentCourse(){  Course = new Course(){ CourseName="Machine Language" } },//Child entity (empty key)
                new StudentCourse(){  Course = new Course(){  CourseId=2 } } //Child entity (with key value)
            }
    };
    
    var context = new SchoolContext();
    context.Entry(student).State = EntityState.Modified;
    
    DisplayStates(context.ChangeTracker.Entries());
    Output:
    Entity: Student, State: Modified
    

    在上面的示例中,context.Entry(student).State = EntityState.Modified将实体附加到上下文,并将指定的EntityState(在本例中为Modified)应用于根实体,而不管其是否包含Key属性值或不。它会忽略图中的所有子实体,并且不会附加或设置其EntityState。
    下表列出了DbContext.Entry(方法的不同行为。

    使用Entry()设置EntityState 具有键值的根实体 具有空值或CLR默认值的根实体 有/没有键值的子实体
    context.Entry(entityGraph).State = EntityState.Added Added Added Ignored
    context.Entry(entityGraph).State = EntityState.Modified Modified Modified Ignored
    context.Entry(entityGraph).State = EntityState.Deleted Deleted Deleted Ignored

    Add()

    DbContext.Add和DbSet.Add方法将实体图附加到上下文,并将“ Added EntityState”设置为根和子实体,而不管它们是否具有键值。

    var student = new Student() { //Root entity (with key value)
        StudentId = 1,
        Name = "Bill",
        Address = new StudentAddress()  //Child entity (with key value)
        {
            StudentAddressId = 1,
            City = "Seattle",
            Country = "USA"
        },
        StudentCourses = new List<StudentCourse>() {
                new StudentCourse(){  Course = new Course(){ CourseName="Machine Language" } },//Child entity (empty key)
                new StudentCourse(){  Course = new Course(){  CourseId=2 } } //Child entity (with key value)
            }
    };
    
    var context = new SchoolContext();
    context.Students.Add(student);
    
    DisplayStates(context.ChangeTracker.Entries());
    
    Output:
    输出:
    Entity: Student, State: Added
    Entity: StudentAddress, State: Added
    Entity: StudentCourse, State: Added
    Entity: Course, State: Added
    Entity: StudentCourse, State: Added
    Entity: Course, State: Added
    

    下表列出了使用DbContext.Add或DbSet.Add方法的图形中每个实体的可能EntityState。

    方法 具有/不具有键值的根实体 有/没有键值的子实体
    DbContext.Add(entityGraph) or DbSet.Add(entityGraph) Added Added

    Update()

    DbContext.Update(和DbSet.Update(方法将实体图附加到上下文,并根据图中是否包含键属性值来设置图中每个实体的EntityState。考虑以下示例。

    var student = new Student() { //Root entity (with key value)
        StudentId = 1,
        Name = "Bill",
        Address = new StudentAddress()  //Child entity (with key value)
        {
            StudentAddressId = 1,
            City = "Seattle",
            Country = "USA"
        },
        StudentCourses = new List<StudentCourse>() {
                new StudentCourse(){  Course = new Course(){ CourseName="Machine Language" } },//Child entity (empty key)
                new StudentCourse(){  Course = new Course(){  CourseId=2 } } //Child entity (with key value)
            }
    };
    
    var context = new SchoolContext();
    context.Update(student);
    
    DisplayStates(context.ChangeTracker.Entries());
    
    Output:
    Entity: Student, State: Modified
    Entity: StudentAddress, State: Modified
    Entity: StudentCourse, State: Added
    Entity: Course, State: Added
    Entity: StudentCourse, State: Added
    Entity: Course, State: Modified
    

    在上面的示例中,Update(方法将Modified状态应用于包含非空键属性值的实体,并将Added状态应用于包含空或默认CLR键值的实体,而不管它们是根实体还是子实体。

    Update() 具有键值的根实体 具有空值或CLR默认值的根实体 具有键值的子实体 空键值的子实体
    DbContext.Update(entityGraph) or DbSet.Update(entityGraph) Modified Added Modified Added

    Remove()

    DbContext.Remove(和DbSet.Remove(方法将Deleted EntityState设置为根实体。

    var student = new Student() { //Root entity (with key value)
        StudentId = 1,
        Name = "Bill",
        Address = new StudentAddress()  //Child entity (with key value)
        {
            StudentAddressId = 1,
            City = "Seattle",
            Country = "USA"
        },
        StudentCourses = new List<StudentCourse>() {
                new StudentCourse(){  Course = new Course(){ CourseName="Machine Language" } },//Child entity (empty key)
                new StudentCourse(){  Course = new Course(){  CourseId=2 } } //Child entity (with key value)
            }
    };
    
    var context = new SchoolContext();
    context.Remove(student);
    
    DisplayStates(context.ChangeTracker.Entries());
    Output:
    Entity: Student, State: Deleted
    Entity: StudentAddress, State: Unchanged
    Entity: StudentCourse, State: Added
    Entity: Course, State: Added
    Entity: StudentCourse, State: Added
    Entity: Course, State: Unchanged
    

    下表列出了每个实体的EntityState上Remove(方法的行为。

    Remove() 具有键值的根实体 具有空值或CLR默认值的根实体 具有键值的子实体 空键值的子实体
    DbContext.Remove(entityGraph) or DbSet.Remove(entityGraph) Deleted Exception Unchanged Added

    因此,在EF Core中使用上述方法时要小心。
    在下一章中,将学习有关如何处理实体图中每个实体的ChangeTracker.TrackGraph(方法。

  • 相关阅读:
    Vmware 添加虚拟磁盘
    2019-2020-2 《网络对抗技术》 Exp3 免杀原理与实践
    Docker 容器更换软件源
    Docker 查看容器 Linux 版本
    OpenMediaVault 5 进阶配置(四) Portainer 管理 Docker
    Portainer 中文文档:部署
    树莓派 部署 Docker 数据库容器
    通过Cookie统计上次网页访问时间
    用JavaMail通过QQ邮箱来发送邮件(第一篇博客,备忘)
    删掉双系统
  • 原文地址:https://www.cnblogs.com/AlexanderZhao/p/12878802.html
Copyright © 2020-2023  润新知