最近遇到了一个 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. kde钱包 忘记密码

    转自 https://forum.suse.org.cn/t/kwallet/4367/2 修改 ~/.config/kwalletrc文件的First Use=false 改成 true 应该可以重 ...

  2. 牛牛与数组 (简单dp)

    题目链接 这种题一看就是dp啊,dp[i][j]表示第i位放j的方案数,转移方程为dp[i][j]=dp[i-1][k]{k<=i||k%i!=0},当然我们可以三层循环来找,但数据显然会超时, ...

  3. apt-get本地软件源搭建

    参考:https://www.cnblogs.com/myitroad/p/4970416.html 试验机器: Ubuntu 12.04.Lubuntu.Debian都可,其他版本应该也没问题,服务 ...

  4. GMM与EM共舞

    GMM,即高斯混合模型(Gaussian Mixture Model),简单地讲,就是将多个高斯模型混合起来,作为一个新的模型,这样就可以综合运用多模型的表达能力.EM,指的是均值最大化算法(expe ...

  5. powerdesigner添加mysql的字符集支持

    一般建模可能都会用到:powerdesigner 但是,在建表的时候,我一直没有找到: DEFAULT CHARACTER SET COLLATE 两个选项.因此,想了个方法,点击:工具栏->d ...

  6. numpy中的meshgrid

    经常遇到meshgrid,一段时间不用就忘记了,记录之 meshgrid用于生成网格点的坐标矩阵(参考https://blog.csdn.net/lllxxq141592654/article/det ...

  7. python3列表(list)

    一.列表(List) 定义:有序的可变的元素集合:通过range函数构造,在python3 中用的时候才会去构造   list = [1,2,3,4,5,'abc',['a',1,2,3],6,7] ...

  8. 【Android】webview javascript 注入方法

    Android中向webview注入js代码可以通过webview.loadUrl("javascript:xxx")来实现,然后就会执行javascript后面的代码. 但是当需 ...

  9. bootstrap弹窗、弹出层、modal

    bootstrap弹窗.弹出层.modal 引入bootstrap的js文件    如下div代码 <div class="modal fade" id="myMo ...

  10. 基于Python & Opencv 图像-视频-处理算法

    Alg1:图像数据格式之间相互转换.png to .jpg(其他的请举一反三) import cv2 import glob def png2jpg(): images = glob.glob('*. ...