c# - 使用 Entity Framework 进行级联插入

标签 c# sql entity-framework

public class User
{
    public int ID { get; set; }

    public string EmailAddress { get; set; }

    public virtual ICollection<Address> Addresses { get; set; }
}

public class Address
{
    public int ID { get; set; }

    public string City { get; set; }

    public string Street { get; set; }

    public string Postcode { get; set; }
}

class TestDbContext : DbContext
{
    public TestDbContext()
        : base("DefaultConnectionString")
    {
    }

    public DbSet<User> Users { get; set; }
    public DbSet<Address> Addresses { get; set; }
}

以上是模型定义和 DbContext 定义。我想为用户添加一个新地址,所以我编写了如下代码:

var context = new TestDbContext();

var user = context.Users.FirstOrDefault(item => item.ID == 1);

user.Addresses.Add(new Address()
{
    City = "City",
    Street = "Street",
    Postcode = "Postcode",
});

context.SaveChanges();

我的疑问是为什么这段代码中执行了3个SQL查询?

  1. 它是在 FirstOrDefault 中生成的

    SELECT TOP (1) 
      [Extent1].[ID] AS [ID], 
      [Extent1].[EmailAddress] AS [EmailAddress]
      FROM [dbo].[Users] AS [Extent1]
      WHERE 1 = [Extent1].[ID]
    
  2. 它是在 user.Addresses.Add 中生成的
    exec sp_executesql N'SELECT 
        [Extent1].[ID] AS [ID], 
        [Extent1].[City] AS [City], 
        [Extent1].[Street] AS [Street], 
        [Extent1].[Postcode] AS [Postcode], 
        [Extent1].[User_ID] AS [User_ID]
        FROM [dbo].[Addresses] AS [Extent1]
        WHERE ([Extent1].[User_ID] IS NOT NULL) 
          AND ([Extent1].[User_ID] = @EntityKeyValue1)',N'@EntityKeyValue1 int',@EntityKeyValue1=1
    
  3. 它是在 SaveChanges 中生成的

    exec sp_executesql N'INSERT [dbo].[Addresses]([City], [Street], [Postcode], [User_ID])
    VALUES (@0, @1, @2, @3)
    SELECT [ID]
    FROM [dbo].[Addresses]
    WHERE @@ROWCOUNT > 0 AND [ID] = scope_identity()',N'@0 nvarchar(max) ,@1 nvarchar(max) ,@2 nvarchar(max) ,@3 int',@0=N'City',@1=N'Street',@2=N'Postcode',@3=1
    

    如何避免第二条 SQL?

最佳答案

当您访问该属性(即 user.Addresses)时,Addresses 导航属性会延迟加载,这就是您获得第二个 SQL 命令的原因。

尝试禁用延迟加载并查看是否有效(不要忘记在 User 的构造函数中初始化 Addresses 属性,例如:

public User()
{
    Addresses = new HashSet<Address>();
}

关于c# - 使用 Entity Framework 进行级联插入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21330165/

相关文章:

java - 如何记录JOOQ执行的生成的sql

c# - EntityFramework 首先使用数据库检测复杂类型

c# - FixDocument 作为报告引擎?

c# - Google 趋势 - 5 次调用后达到配额限制

c# - 如何在 Asp.Net Core 中自定义开发者异常页面?

C++ SQL 数据库库比较

sql - 选择具有多个“where”字段的语句,使用相同的值而不重复文本

c# - 数据库初始化后无法禁用迁移

LINQ 查询语法到方法语法

c# - 如何填充 GridView 异步