zoukankan      html  css  js  c++  java
  • 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(方法。

  • 相关阅读:
    《WF编程》系列之32 基本活动:条件与规则 4.5 条件与规则
    《WF编程》系列之31 基本活动:事务(Transactions)与补偿(Compensation) 4.4 事务(Transactions)与补偿(Compensation)
    《WF编程》系列之30 基本活动:错误处理
    《WF编程》系列之33 基本活动:Web Services 4.6 Web Services
    《WF编程》系列之36 自定义活动:如何创建自定义活动?活动的组合 5.2 如何创建自定义活动?
    《WF编程》系列之35 自定义活动:为何创建自定义活动? 5 自定义活动
    《WF编程》系列之29 本地通信事件:HandleExternalEventActivity & 活动生成器 4.2.2 HandleExternalEventActivity
    《WF编程》系列之34 基本活动:状态活动 到目前为止,我们所讨论的工作流都是顺序工作流,而WF还支持另外一种工作流机制状态机(StateMachine)工作流,本节就来介绍这些在状态机工作流中工作的活动.
    《WF编程》系列之37 打开黑盒子:属性升级.
    《WF编程》系列之28 本地通信事件:CallExternalMethodActivity
  • 原文地址:https://www.cnblogs.com/AlexanderZhao/p/12878802.html
Copyright © 2011-2022 走看看