EF 6 DB-First系列--在EF 6中附加未被跟踪实体的方法

在EF 6中附加未被跟踪实体的方法

在这里,您将了解Entity Framework 6.x中将断开连接的实体附加到上下文的不同方法。

所谓断开连接的实体是指: 一个普通的POCO类,其并未被纳入EF的DbContext上下文管理范围内,即DbContext无法跟踪其状态。

在断开连接的场景下保存实体与在已连接的场景下保存实体不同。当我们得到一个不连接的实体图或者甚至是单个不连接的实体时,我们需要做两件事。首先,我们需要将实体附加到新的上下文实例中,并使上下文知道这些实体。其次,手动为每个实体设置适当的EntityState,因为实例不知道在断开连接的实体上执行的任何操作,因此它不能自动应用适当的EntityState。

下图说明了这个过程。

在这里插入图片描述
Entity Framework提供了以下方法,将断开连接的实体附加到上下文,并将EntityState设置为实体图中的每个实体。

  • DbContext.Entry()
  • DbSet.Add()
  • DbSet.Attach()

DbContext.Entry()

DbContext类的Entry()方法返回指定实体的DbEntityEntry实例。DbEntityEntry对象提供了关于指定实体的各种信息,以及对实体执行操作的能力。最重要的是,我们可以使用State属性更改指定实体的EntityState,如下所示。

context.Entry(entity).state = EntityState.Added/Modified/Deleted

Entry方法将整个实体图附加到上下文,并将指定的状态附加到父实体,还将不同的EntityState设置到其他实体。考虑下面的例子。

var student = new Student() { //Root entity (empty key)
	StudentName = "Bill",
	StandardId = 1,
	Standard = new Standard()   //Child entity (with key value)
	 {
	      StandardId = 1,
	      StandardName = "Grade 1"
	  },
        Courses = new List<Course>() {
            new Course(){  CourseName = "Machine Language" }, //Child entity (empty key)
            new Course(){  CourseId = 2 } //Child entity (with key value)
        }
};


using (var context = new SchoolDBEntities())
{
    context.Entry(student).State = EntityState.Added;  //设置student实体状态为Added

    foreach (var entity in context.ChangeTracker.Entries()){ //遍历当前上下文实例中跟踪的所有实体
        Console.WriteLine("{0}: {1}", entity.Entity.GetType().Name, entity.State);
    } 
}

Output:
Student: Added
Standard: Added
Course: Added
Course: Added

在上面的例子中,Studnet实体图包括Standard和Course实体。context.Entry(student).State = EntityState.Added;为父实体以及所有其他子实体设置Added状态,而不管子实体是否包含空键值。因此,建议谨慎使用Entry()方法。

下表列出了Entry()方法的方法。

父Entity 状态Entity子实体状态
AddedAdded
ModifiedUnchanged
DeletedAll child entities will be null

DbSet.Add()

DbSet.Add()方法将整个实体图附加到一个上下文中,并自动将Added状态应用到所有实体。

//未被纳入上下文管理的实体
Student disconnectedStudent = new Student() { StudentName = "New Student" };

disconnectedStudent.StudentAddress = new StudentAddress() { Address1 = "Address", City = "City1" };


using (var context = new SchoolDBEntities())
{
    //DbSet.Add()方法将整个实体图附加到一个上下文中,并自动将Added状态应用到所有实体。
    context.Students.Add(disconnectedStudent); 
                
    // 获取DbEntityEntry实例,检查指定实体的EntityState
    var studentEntry = context.Entry(disconnectedStudent);
    var addressEntry = context.Entry(disconnectedStudent.StudentAddress);

    Console.WriteLine("Student: {0}", studentEntry.State);
    Console.WriteLine("StudentAddress: {0}", addressEntry.State);
}

Output:
Student: Added
StudentAddress: Added

DbSet.Add()方法将整个实体图附加到一个上下文,并将Added 状态附加到每个实体。调用context.Savechanges()将为所有实体执行INSERT命令,这将在适当的数据库表中插入新记录。

DbSet.Attach()

DbSet.Attach()方法将整个实体图附加到具有Unchanged实体状态的新上下文。

//未被纳入上下文管理的实体
Student disconnectedStudent = new Student() { StudentName = "New Student" };
disconnectedStudent.StudentAddress = new StudentAddress() { Address1 = "Address", City = "City1" };

using (var context = new SchoolDBEntities())
{
    context.Students.Attach(disconnectedStudent);
                
    // 获取DbEntityEntry实例,检查指定实体的EntityState
    var studentEntry = context.Entry(disconnectedStudent);
    var addressEntry = context.Entry(disconnectedStudent.StudentAddress);

    Console.WriteLine("Student: {0}",studentEntry.State);
    Console.WriteLine("StudentAddress: {0}",addressEntry.State);
}

Output:
Student: Unchanged
StudentAddress: Unchanged

参考

https://www.entityframeworktutorial.net/
https://msdn.microsoft.com/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值