- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
当使用像 MySQL 这样的网络数据库时,DbContext 应该是短暂的,但是根据 https://www.entityframeworktutorial.net/EntityFramework4.3/persistence-in-entity-framework.aspx使用本地数据库(例如 SQLite)时,DbContext 可以长期存在。
我的应用程序使用长期存在的 DbContext 来处理 HDD 上的 SQLite,我想将多对多实体复制到另一个 DbContext 以用于 USB 上相同类型的 SQLite 数据库。
我正在使用代码优先方法。
public class Student
{
public Student()
{
this.Courses = new HashSet<Course>();
}
public int StudentId { get; set; }
[Required]
public string StudentName { get; set; }
public virtual ICollection<Course> Courses { get; set; }
}
public class Course
{
public Course()
{
this.Students = new HashSet<Student>();
}
public int CourseId { get; set; }
public string CourseName { get; set; }
public virtual ICollection<Student> Students { get; set; }
}
DbContextHDD 包含学生 StudentA、StudentB 和 StudentC 以及类(class) Course1、Course2 和 Course3:
StudentA attends Course1 and Course3
StudentB attends Course2 and Course3
StudentC attends Course1 and Course2
DbContextUSB 不包含学生和类(class)。
var courses = DbContextHDD.Courses.AsNoTracking();
List<Student> students = new List<Student>();
foreach(Course course in courses)
{
foreach(Student student in course.Students)
{
if(!students.Any(s => s.StudentId == student.StudentId))
{
students.Add(student);
}
}
}
Debug.WriteLine(students.Count); // output: 3
Debug.WriteLine(DbContextUSB.Students.Local.Count); // output: 0
DbContextUSB.Students.AddRange(students);
Debug.WriteLine(DbContextUSB.Students.Local.Count); // output: 4
DbContextUSB.SaveChanges(); // exception: UNIQUE constraint failed
DbContextUSB.Courses.AddRange(courses);
DbContextUSB.SaveChanges();
为什么在我将 3 个不同的学生插入到具有 0 个学生的 DbSet 后,有 4 个学生(3 个唯一的和 1 个重复的)?执行此操作的正确方法是什么?
正如我所说,我正在使用长期使用的 DbContext,因为我正在使用 SQLite。
最佳答案
首先,不要使用AsNoTracking
:
var courses = DbContextHDD.Courses. ...
其次,包含
需要的数据:
var courses = DbContextHDD.Courses
.Include(c => c.Students)
.ToList();
第三,将类(class)添加到其他上下文:
DbContextUSB.Courses.AddRange(courses);
DbContextUSB.SaveChanges();
你可能不相信,但本质上就是这样!
一个警告是您应该在源上下文中禁用代理创建:
DbContextHDD.Configuration.ProxyCreationEnabled = false;
否则 EF 会创建代理对象,这些对象具有对它们来自的上下文的引用。它们不能附加到另一个上下文。
另一个是可能会有学生不参加类(class)。查询类(class)时您会想念它们。所以你必须单独添加它们:
var lazyStudents = DbContextHDD.Students.Where(s => s.Courses.Count() == 0).ToList();
...
DbContextUSB.Students.AddRange(lazyStudents);
...
DbContextUSB.SaveChanges();
为什么会这样?
如果没有跟踪, Entity Framework 无法检测到 StudentA 在Course1 与 Course3 中的学生相同。结果,学生 A在 Course3 中是一个新的 Student
实例。您最终将有 6 个学生,3 个重复(如果 StudentName
上没有唯一索引来阻止这种情况)。通过跟踪,EF 确实检测到两个类(class)都有相同的 Student
实例。
将实体添加到上下文时,EF 还会标记嵌套当实体尚未附加到上下文时,将实体标记为 Added
。这就是为什么只添加类(class)就足够了,这就是为什么EF不添加类(class)的原因当类(class)包含相同的学生实例时提示。
由于添加的类(class)已正确填充其Students
集合,因此 EF 还将所需的联结记录插入到 StudentCourse
表中。这并没有发生在您的代码中(也许,或部分发生,稍后见)。
现在你为什么有 4 个学生?
查看类(class):
Course1 StudentA*, StudentC*
Course2 StudentB*, StudentC
Course3 StudentA , StudentB
由于 AsNoTracking
所有学生都是不同的实例,但只有标记*的学生在 students
中,因为您添加它们的方式。但这是棘手的部分。即使使用 AsNoTracking()
, Entity Framework 也会对在一个查询中具体化的相关实体执行关系修复。这意味着 foreach(Course course in courses)
循环生成具有填充的 Students
集合的类(class),其中每个学生在其 Courses
集合中都有一门类(class).几乎不可能跟踪到底发生了什么,尤其是。因为调试也会触发延迟加载,但可以肯定的是,行...
DbContextUSB.Students.AddRange(students);
还将它们的嵌套类(class)和它们的学生标记为已添加
,因为它们最终是不同的实例。在这种情况下,最终结果是将另一个学生实例添加到缓存中。此外,创建了许多联结记录,但不一定是正确的。
结论是 EF 是克隆对象图的好工具,但必须正确填充图、正确的关系并且没有重复项,并且应该一次性添加。
关于c# - Entity Framework 6.2 将多对多从一个 DbContext 复制到另一个 DbContext,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57180967/
我正在编写一个应用程序,允许用户创建一个“问卷”,然后向其中添加问题。我正在使用核心数据来存储信息。我创建了一个问卷实体,并与问题实体建立了“一对多”关系。我的问题是,如果要允许用户复制(复制)整个调
有没有办法复制或复制 SharedPreference?或者我需要从一个变量中获取每个变量,然后将它们放入另一个变量中吗? 最佳答案 尝试这样的事情: //sp1 is the shared pref
下面的(A)和(B)有区别吗? (假设 NON ARC,如果重要的话) // --- (A) --- @interface Zoo : NSObject{} @property (copy) Dog
我正在尝试将 mysql SELECT 查询保存到文件中,如下所示: $result = mysqli_query($db,$sql); $out = fopen('tmp/csv.csv', 'w'
我需要创建一个 CVPixelBufferRef 的副本,以便能够使用副本中的值以按位方式操作原始像素缓冲区。我似乎无法使用 CVPixelBufferCreate 或 CVPixelBufferCr
我在 Source 文件夹中有一个 Active wave 录音 wave-file.wav。我需要使用新名称 wave-file-copy.wav 将此文件复制到 Destination 文件夹。
在使用 GNU Autotools 构建的项目中,我有一个脚本需要通过 make 修改以包含安装路径。这是一个小例子: configure.ac: AC_INIT(foobar, 1.0) AC_PR
我想将 SQL 的行复制到同一个表中。但是在我的表中,我有一个“文本”列。 使用此 SQL: CREATE TEMPORARY TABLE produit2 ENGINE=MEMORY SELECT
谁能给我解释一下 df2 = df1 df2 = df1.copy() df3 = df1.copy(deep=False) 我已经尝试了所有选项并执行了以下操作: df1 = pd.DataFram
Hazelcast 是否具有类似于 Ehcache 的复制? http://www.ehcache.org/generated/2.9.0/pdf/Ehcache_Replication_Guide.
我有以下拓扑。一个 Ubuntu 16.04。运行我的全局 MySQL 服务器的 Amazon AWS 上的实例。我想将此服务器用作许多本地主服务器(Windows 机器 MySQL 服务器)的从服务
使用 SQLyog,我正在测试表中是否设置了正确的值。我尝试过 SELECT type_service FROM service WHERE email='test@gmail.com' 因此,只输出
有人可以提供一些关于如何配置 ElasticSearch 进行复制的说明。我在 Windows 中运行 ES,并且了解如果我在同一台服务器上多次运行 bat 文件,则会启动一个单独的 ES 实例,并且
一 点睛 ThreadGroup 复制线程的两个方法。 public int enumerate(Thread list[]) // 会将 ThreadGroup 中的 active 线程全部复制到
一 点睛 ThreadGroup 复制线程组的两个方法。 public int enumerate(ThreadGroup list[]) // 相对于 enumerate(list,true) pu
官方documentation Cassandra 说: Configure the keyspace and create the new datacenter: Use ALTER KEYSPAC
This question already has answers here: How to weight smoothing by arbitrary factor in ggplot2? (2个答
我们有一个表格来表明对各种俱乐部的兴趣。输出将数据记录在 Excel 电子表格中,其中列有他们的首选姓名、姓氏、电子邮件、代词,以及他们感兴趣的俱乐部的相应列中的“1”(下面的模型)。 我们希望为俱乐
This question already has answers here: Closed 8 years ago. Possible Duplicate: In vim, how do I get
如何复制形状及其所在的单元格?当我手动复制时,形状会跟随单元格,但是当我使用宏进行复制时,我会得到除形状之外的所有其他内容。 Cells(sourceRow, sourceColumn).Copy C
我是一名优秀的程序员,十分优秀!