最近遇到了一个 EF Core 的恐怖问题,在添加数据时竟然会自动删除数据库中已存在的数据,经过追查发现是一个多余的实体关系配置引起的。

modelBuilder.Entity<Question>()
.HasOne(q => q.Owner)
.WithOne();

罪魁祸首就是上面的 WithOne()

今天写了个非常简单的控制台程序重现了这个问题。

实体类 Question 的定义

public class Question
{
public int Id { get; set; }
public string Title { get; set; }
public int UserId { get; set; }
public User Owner { get; set; }
}

实体类 User 的定义

public class User
{
public int Id { get; set; }
public string Name { get; set; }
}

实体关系配置

modelBuilder.Entity<Question>()
.HasOne(q => q.Owner)
.WithOne();

触发问题的实体查询与添加代码

class Program
{
static async Task Main(string[] args)
{
var conn = "server=.;database=question;integrated security=true"; var host = new HostBuilder()
.ConfigureServices(services =>
{
services.AddDbContext<MyDbContext>(options => options.UseSqlServer(conn));
}).Build(); using (var db = host.Services.GetRequiredService<MyDbContext>())
{
var newQuestion = new Question
{
Title = "test " + DateTime.Now.ToLongDateString(),
Owner = await db.Set<User>().FirstAsync(u => u.Id == 1)
}; var latestQuestion = await db.Set<Question>()
.Where(q => q.UserId == 1).OrderByDescending(q => q.Id).FirstOrDefaultAsync(); db.Set<Question>().Add(newQuestion);
await db.SaveChangesAsync();
}
}
}

EF Core 生成的在 INSERT 之前的 DELETE SQL 语句

exec sp_executesql N'SET NOCOUNT ON;
DELETE FROM [Question]
WHERE [Id] = @p0;
SELECT @@ROWCOUNT;

问题分析(只是个人猜想)

上面的代码中,创建一个新的 Question 实例时,与一个从数据库查询出来的 Id 为 1 的 User 实例进行了关联,此时这个 User 实例进入 EF Core 的跟踪范围,但这个新建的 Question 实例还没被 EF Core 跟踪。后来使用同样的 UserId 从数据库查询 Question ,查询出来的 Question 实例由于 WithOne 实体关系从而与已经被跟踪的 User 实例(因为 UserId 一样)进行了关联。此时被 EF Core 跟踪到的实体状态是:Id 为 1 的 User 实体与从数据库查询得到的 Id 为 x 的 Question 实体进行了一对一关联。而在 db.Set<Question>().Add(newQuestion) 时,EF Core 跟踪到了实体状态的变化 —— User 实体与一个没有 Id 的新 Question 实体关联了,对于这样的状态变化,EF Core 理所当然地做出了“正确的决定” —— 删除之前关联的 Question 实体,添加新的 Question 实体。

解决方法

去掉多条的 WithOne()

示例代码

重现这个问题的完整示例代码:https://github.com/cnblogs-dudu/efcore-unexpected-deletion

WithOne 实体关系引起 EF Core 自动删除数据的更多相关文章

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

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

  2. 文章翻译:ABP如何在EF core中添加数据过滤器

    原文地址:https://aspnetboilerplate.com/Pages/Documents/Articles%5CHow-To%5Cadd-custom-data-filter-ef-cor ...

  3. Asp.net core下利用EF core实现从数据实现多租户(1)

    前言 随着互联网的的高速发展,大多数的公司由于一开始使用的传统的硬件/软件架构,导致在业务不断发展的同时,系统也逐渐地逼近传统结构的极限. 于是,系统也急需进行结构上的升级换代. 在服务端,系统的I/ ...

  4. Asp.net core下利用EF core实现从数据实现多租户(3): 按Schema分离 附加:EF Migration 操作

    前言 前段时间写了EF core实现多租户的文章,实现了根据数据库,数据表进行多租户数据隔离. 今天开始写按照Schema分离的文章. 其实还有一种,是通过在数据表内添加一个字段做多租户的,但是这种模 ...

  5. ef core自动映射

    原回答:https://stackoverflow.com/questions/26957519/ef-core-mapping-entitytypeconfiguration 一.反射 protec ...

  6. Asp.net core下利用EF core实现从数据实现多租户(2) : 按表分离

    前言 在上一篇文章中,我们介绍了如何根据不同的租户进行数据分离,分离的办法是一个租户一个数据库. 也提到了这种模式还是相对比较重,所以本文会介绍一种更加普遍使用的办法: 按表分离租户. 这样做的好处是 ...

  7. 使用ef core自动生成mysql表和数据编码的问题

    mysql默认的编码是不支持中文的,需要改成utf8编码格式. 而我使用的Pomelo.EntityFrameworkCore.MySql组件生成mysql库和表,他是使用默认编码的. 网上大多说修改 ...

  8. EF Core 2.0 已经支持自动生成父子关系表的实体

    现在我们在SQL Server数据库中有Person表如下: CREATE TABLE [dbo].[Person]( ,) NOT NULL, ) NULL, ) NULL, ) NULL, [Cr ...

  9. EF Core 2.1 支持数据库一对一关系

    在使用EF Core和设计数据库的时候,通常一对多.多对多关系使用得比较多,但是一对一关系使用得就比较少了.最近我发现实际上EF Core很好地支持了数据库的一对一关系. 数据库 我们先来看看SQL ...

随机推荐

  1. 分布式系列四: HTTP及HTTPS协议

    分布式系列四: HTTP及HTTPS协议 非常全面的一篇HTTP的文章: 关于HTTP协议,一篇就够了 还有一个帮助理解HTTPS的文章: 也许,这样理解HTTPS更容易 本文的一些描述摘自这篇文章 ...

  2. 关于NB-IoT的十大问题和答案【转】

    转自:https://blog.csdn.net/u011943791/article/details/80287053 今天大白来给各位解答一下关于NB-IoT的十大问题. 问1:NB-IoT模块还 ...

  3. Alpha 冲刺 (9/10)

    目录 摘要 团队部分 个人部分 摘要 队名:小白吃 组长博客:hjj 作业博客:冲刺倒计时之9 团队部分 后敬甲(组长) 过去两天完成了哪些任务 答辩准备中 和大佬们跟进进度 接下来的计划 准备答辩 ...

  4. Python基础【第一篇】

     一.Python简介 Python的创始人(Guido von Rossum 荷兰人),Guido希望有一种语言既能像C一样方便地调用操作系统的功能接口,也能像shell脚本一样,轻松地实现编程,A ...

  5. bootstrap轮播图 两侧半透明阴影

    用bootstrap轮播图:Carousel插件,图片两侧影音实在碍眼,想去掉,首先发现有css里由opacity: 0.5这个东西来控制,全部改成opacity: 0.0,发现指示箭头也看不见了. ...

  6. Google Android SDK开发范例大全笔记 一

    方法讲解 1 获取手机分辨率方法 DisplayMetrics private void getDiaplayMetrics() { DisplayMetrics dm = new DisplayMe ...

  7. 微信支付的安全漏洞之XXE

    1.场景:国外安全社区公布微信支付官方SDK存在严重漏洞,可导致商家服务器被入侵(绕过支付的效果).目前,漏洞详细信息以及攻击方式已被公开,影响范围巨大(已确认陌陌.vivo因使用该SDK而存在该漏洞 ...

  8. jmeter测试wordpress使用base64进行鉴权

    1.下载插件 对密码进行加密 2.安装插件 3.使用插件 4.使用base64对上面获取到的密码进行二次加密 echo -n "用户:密码" | base64 将以上命令键入lin ...

  9. Python内置模块之configparse

    一.概述 1.1.处理的文件形式 configparse 主要是用来处理类似于windows的 ini文件,这个文件的特点是有多个节(section),每个节下会存储多个k=v的值 如下配置 [har ...

  10. sort实现ip排序

    说明: 工具:sort linux自带        ”-t” : 表示以那个字符做分割        “-k” :和-t结合使用,表示取那一段为关键字进行排序,后面跟数据,1…n,表示取第几段,也可 ...