1. 江湖人士首页
  2. IT江湖

EF Core 中使用无连接跟踪图

上一篇文章中,学习了在有连接场景中EF Core的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

在上面的示例中,studStudent实体图的实例,其包括StudentAddressStudentCourse实体的引用。 context.Attach(stud).State = EntityState.Addedstud实体图附加到上下文并为其设置已添加状态。

Attach()添加方法设置EntityState到根实体(在这种情况下,Student不管其是否包含密钥值或没有)。如果子实体包含键值,则它将被标记为未更改,否则将标记为已添加。上面示例的输出显示Student实体已添加EntityState,具有非空键值的子实体具有未更改EntityState,具有空键值的子实体具有已添加状态。

下表列出了Attach()在设置不同EntityState的断开连接的实体图时方法的行为。

Attach()
具有Key的根实体

具有Empty或CLR默认值的Root实体

具有键值的子实体

具有空或CLR默认值的子实体
context.Attach(entityGraph).State = EntityState.AddedAddedAddedUnchangedAdded
context.Attach(entityGraph).State = EntityState.ModifiedModifiedExceptionUnchangedAdded
context.Attach(entityGraph).State = EntityState.DeletedDeletedExceptionUnchangedAdded

Entry()方法

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

Output:
Entity: Student, State: Modified

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

下表列出了该DbContext.Entry()方法的不同行为。

使用Entry() 设置实体状态根实体有Key
具有Empty或CLR默认值的Root实体

不管子实体有无Key
context.Entry(entityGraph).State = EntityState.AddedAddedAddedIgnored
context.Entry(entityGraph).State = EntityState.ModifiedModifiedModifiedIgnored
context.Entry(entityGraph).State = EntityState.DeletedDeletedDeletedIgnored

Add()方法

DbContext.AddDbSet.Add方法附加实体图来添加上下文并设置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.AddDbSet.Add方法的图中每个实体的可能EntityState 。

方法不管根实体有无Key不管子实体有无Key
DbContext.Add(entityGraph) or DbSet.Add(entityGraph)AddedAdded

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()
具有键值的根实体

具有Empty或CLR默认值的Root实体

具有键值的子实体

具有空键值的子实体
DbContext.Update(entityGraph) or DbSet.Update(entityGraph)ModifiedAddedModifiedAdded

Remove()方法

DbContext.Remove()DbSet.Remove()方法已删除设置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 } }
        }
};
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

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

Remove()
具有键值的根实体

具有Empty或CLR默认值的Root实体

具有键值的子实体

具有空键值的子实体
DbContext.Remove(entityGraph) or DbSet.Remove(entityGraph)DeletedExceptionUnchangedAdded

因此,在EF Core中使用上述方法时要小心。

ChangeTracker.TrackGraph()在下一章中 了解处理实体图中每个实体的方法。

Namesilo优惠:新用户省 $1 域名注册-优惠码:45D%UYTcxYuCloZ 国外最便宜域名!点击了解更多

特别优惠:免费赠送 $50 Vultr主机-限时优惠!英文站必备海外服务器!点击了解更多

VPS优惠:搬瓦工优惠码:BWH34QMFYT2R 最高省6.38%你懂的主机-一直优惠!点击了解更多

原创文章,作者:江小编,如若转载,请注明出处:https://jhrs.com/2019/27214.html

扫码关注【江湖人士】公众号,您会获得关于国外被动收入的最新资讯

WA付费会员QQ群:387027533,加这个群需要回答您的WA会员名,待核实后予以通过

普通QQ交流群:178758794,可分享交流建站的各类经验和知识

发表评论

电子邮件地址不会被公开。 必填项已用*标注

11 + 14 =