在EF Core的DbContext中,我们可以通过DbContext或DbSet的Attach方法,来让DbContext上下文来跟踪(track)一个实体对象,假设现在我们有User实体对象,其UserCode为Key属性:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; namespace EFCoreDB.Entities
{
public partial class User
{
public User()
{
UserRole = new HashSet<UserRole>();
} public int Id { get; set; } [Key]
public string UserCode { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string MailAddress { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public string CompanyCode { get; set; }
public DateTime? CreateTime { get; set; }
public int? DataStatus { get; set; } public ICollection<UserRole> UserRole { get; set; }
}
}

现在我们使用DbSet的Attach方法将两个UserCode都为"User001"的User实体Attach到一个DbContext:

using EFCoreDB.Entities;
using System; namespace EFCoreDB
{
class Program
{
static void Main(string[] args)
{
using (FinanceDigitalToolContext dbContext = new FinanceDigitalToolContext())
{
User user = new User() { UserCode = "User001", Username = "Tom" };
dbContext.User.Attach(user); user = new User() { UserCode = "User001", Username = "Jim" };
dbContext.User.Attach(user); dbContext.SaveChanges();
} Console.WriteLine("Press key to quit...."); Console.ReadLine();
}
}
}

运行结果如下:

结果在Attach第二个User实体的时候代码抛出了异常,异常信息如下:

The instance of entity type 'User' cannot be tracked because another instance with the same key value for {'UserCode'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values.

异常信息显示,当前DbContext中已经有一个相同UserCode值的实体被跟踪了,所以Attach第二个User实体的时候失败了。

同样如果我们改为用DbContext的Attach方法来添加第二个User实体也会失败:

using EFCoreDB.Entities;
using System; namespace EFCoreDB
{
class Program
{
static void Main(string[] args)
{
using (FinanceDigitalToolContext dbContext = new FinanceDigitalToolContext())
{
User user = new User() { UserCode = "User001", Username = "Tom" };
dbContext.User.Attach(user); user = new User() { UserCode = "User001", Username = "Jim" };
dbContext.Attach(user); dbContext.SaveChanges();
} Console.WriteLine("Press key to quit...."); Console.ReadLine();
}
}
}

但是如果现在我们Attach一个User实体的两个引用是不会报错的,如下所示:

using EFCoreDB.Entities;
using System; namespace EFCoreDB
{
class Program
{
static void Main(string[] args)
{
using (FinanceDigitalToolContext dbContext = new FinanceDigitalToolContext())
{
User user1 = new User() { UserCode = "User001", Username = "Tom" };//实体User的第一个引用user1
dbContext.User.Attach(user1);//Attach user1 User user2 = user1;//实体User的第二个引用user2,user1和user2实际上指向相同的User实体对象
dbContext.User.Attach(user2);//Attach user2,不会报错 dbContext.SaveChanges();
} Console.WriteLine("Press key to quit...."); Console.ReadLine();
}
}
}

结果如下,没有报错:

这说明当我们用Attach方法将一个User实体添加到EF Core的DbContext中进行跟踪时,DbContext会判断当前添加的实体是否和DbContext.ChangeTracker.Entries中被跟踪的所有实体是同一个对象,如果是同一个对象,那么其实只是把DbContext.ChangeTracker.Entries中所跟踪实体的EntityState更改为Unchanged,我们可以用下面代码来看看User实体两次Attach后的EntityState值:

using EFCoreDB.Entities;
using Microsoft.EntityFrameworkCore;
using System; namespace EFCoreDB
{
class Program
{
static void Main(string[] args)
{
using (FinanceDigitalToolContext dbContext = new FinanceDigitalToolContext())
{
User user1 = new User() { UserCode = "User001", Username = "Tom" };//实体User的第一个引用user1
dbContext.User.Attach(user1);//Attach user1
dbContext.Entry(user1).State = EntityState.Added;//修改user1实体的EntityState为Added
Console.WriteLine($"user1的EntityState为:{dbContext.Entry(user1).State.ToString()}");//显示user1实体的EntityState User user2 = user1;//实体User的第二个引用user2,user1和user2实际上指向相同的User实体对象
dbContext.User.Attach(user2);//Attach user2,不会报错
Console.WriteLine($"user1的EntityState为:{dbContext.Entry(user1).State.ToString()}");//显示user1实体的EntityState,Attach user2后,user1实体的EntityState变为Unchanged dbContext.SaveChanges();
} Console.WriteLine("Press key to quit...."); Console.ReadLine();
}
}
}

结果如下:

EF Core中Key属性相同的实体只能被跟踪(track)一次的更多相关文章

  1. EF Core中怎么实现自动更新实体的属性值到数据库

    我们在开发系统的时候,经常会遇到这种需求数据库表中的行被更新时需要自动更新某些列. 数据库 比如下面的Person表有一列UpdateTime,这列数据要求在行被更新后自动更新为系统的当前时间. Pe ...

  2. EF Core中如何通过实体集合属性删除从表的数据

    假设在数据库中有两个表:Person表和Book表,Person和Book是一对多关系 Person表数据: Book表数据: 可以看到数据库Book表中所有的数据都属于Person表中"F ...

  3. [小技巧]EF Core中如何获取上下文中操作过的实体

    原文地址:https://www.cnblogs.com/lwqlun/p/10576443.html 作者:Lamond Lu 源代码:https://github.com/lamondlu/EFC ...

  4. EF Core 中多次从数据库查询实体数据,DbContext跟踪实体的情况

    使用EF Core时,如果多次从数据库中查询一个表的同一行数据,DbContext中跟踪(track)的实体到底有几个呢?我们下面就分情况讨论下. 数据库 首先我们的数据库中有一个Person表,其建 ...

  5. 9.翻译系列:EF 6以及EF Core中的数据注解特性(EF 6 Code-First系列)

    原文地址:http://www.entityframeworktutorial.net/code-first/dataannotation-in-code-first.aspx EF 6 Code-F ...

  6. 9.4 翻译系列:EF 6以及 EF Core中的NotMapped特性(EF 6 Code-First系列)

    原文链接:http://www.entityframeworktutorial.net/code-first/notmapped-dataannotations-attribute-in-code-f ...

  7. EF Core 中DbContext不会跟踪聚合方法和Join方法返回的结果,及FromSql方法使用讲解

    EF Core中: 如果调用Queryable.Count等聚合方法,不会导致DbContext跟踪(track)任何实体. 此外调用Queryable.Join方法返回的匿名类型也不会被DbCont ...

  8. EF Core中如何正确地设置两张表之间的关联关系

    数据库 假设现在我们在SQL Server数据库中有下面两张表: Person表,代表的是一个人: CREATE TABLE [dbo].[Person]( ,) NOT NULL, ) NULL, ...

  9. 项目开发中的一些注意事项以及技巧总结 基于Repository模式设计项目架构—你可以参考的项目架构设计 Asp.Net Core中使用RSA加密 EF Core中的多对多映射如何实现? asp.net core下的如何给网站做安全设置 获取服务端https证书 Js异常捕获

    项目开发中的一些注意事项以及技巧总结   1.jquery采用ajax向后端请求时,MVC框架并不能返回View的数据,也就是一般我们使用View().PartialView()等,只能返回json以 ...

随机推荐

  1. Node.js开发——MongoDB与Mongoose

    为了保存网站的用户数据和业务数据,通常需要一个数据库.MongoDB和Node.js特别般配,因为MongoDB是基于文档的非关系型数据库,文档是按BSON(JSON的轻量化二进制格式)存储的,增删改 ...

  2. 谈谈HTML5中的history.pushSate方法,弥补ajax导致浏览器前进后退无效的问题

    移动端为了减少页面请求,有时候需要通过单页面做成多页面的效果,最近有这么个需求,表单填完后执行第一步,然后执行第二步,第二步执行完后再执行第三步,每一步都要保留之前的数据.这种情况用单页面实现再合适不 ...

  3. orcale数据恢复

    在操作数据时,不小心改错了表中的数据,想恢复到之前的数据,则可用以下方法: 1.首先我们需要通过dbms_flashback.get_system_change_number,它可以获取系统当前的SC ...

  4. chrome 控制台里 打印对象

    我们经常使用 chrome 的 控制台 console.log()     打印 但有时候我们需要把一个对象复制下来(而这个对象嵌套比较深) 打印出来的我们不好复制 如下图 我们可以使用谷歌控制台的c ...

  5. Qt 资料大全

    https://blog.csdn.net/liang19890820/article/details/51752029 简述 发福利了.发福利了.发福利了,重要的事情说三遍... 为了方便更多Qte ...

  6. 第四次作业——第一次scrum冲刺

    1.小组第一次冲刺任务 对Github上的HUSTOJ开源项目进行Fork,搭建基本环境 2.用户需求 (1)部分基本功能显示在首页 (2)能够提交题目并判题,并对自己所提交的题目正确性进行反馈,能够 ...

  7. 关于YARN的基本结构

  8. c#编程指南(三) 泛型委托(Generic Delegate)

    泛型委托实际上就是一个.NET Framework预定义的委托,基本涵盖了所有常用的委托,所以一般不用用户重新声明啦. 很简单,看下面简单的小例子: //void method(); Action t ...

  9. Oracle案例01——ORA-09925: Unable to create audit trail file

    2018年春节后第一天上班就遇到一个审计日志无法写入的问题,具体解决思路如下. 一.错误日志 数据库错误日志内容: Fri Feb 23 11:16:30 2018OS Audit file coul ...

  10. 【Leetcode】【Medium】Linked List Cycle II

    Given a linked list, return the node where the cycle begins. If there is no cycle, return null. 解题: ...