C# 带有实体框架的级联插入
我的疑问是,为什么在这段代码中会执行3个SQL查询?C# 带有实体框架的级联插入,c#,sql,entity-framework,C#,Sql,Entity Framework,我的疑问是,为什么在这段代码中会执行3个SQL查询? 它是在FirstOrDefault中生成的 var context = new TestDbContext(); var user = context.Users.FirstOrDefault(item => item.ID == 1); user.Addresses.Add(new Address() { City = "City", Street = "Street", Postcode = "Postc
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();
选择顶部(1)
[Extent1].[ID]作为[ID],
[Extent1].[EmailAddress]作为[EmailAddress]
来自[dbo].[Users]作为[Extent1]
其中1=[Extent1].[ID]
您是否尝试过稍微更改类定义: 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 现在你可以写:
public class Address
{
public int ID { get; set; }
public string City { get; set; }
public string Street { get; set; }
public string Postcode { get; set; }
public virtual User User { get; set;}
}
当您访问属性时,
Addresses
nav属性是延迟加载的(即,user.Addresses
),这就是您获得第二个SQL命令的原因
尝试禁用延迟加载并查看其是否有效(不要忘记在用户的构造函数中初始化地址
属性,例如:
var context = new TestDbContext();
var user = context.Users.FirstOrDefault(item => item.ID == 1);
context.Addresses.Add(new Address()
{
City = "City",
Street = "Street",
Postcode = "Postcode",
User = user
});
context.SaveChanges();
公共用户()
{
地址=新的HashSet();
}
正如前面所指出的,这里的问题是您的地址
属性是一个导航属性,因此当您访问它时,EF会生成一个选择
语句来加载集合。为避免发生这种情况,您有两个选项:
当您加载用户时,请立即加载地址,这样您在第一次加载用户时就会受到影响,例如用户。包括(x=>x.addresses)
通过使地址
属性为非虚拟属性,禁用该特定属性上的延迟加载
您甚至可以阻止前两个查询
您已经知道用户的ID值,因此只需在Address
中设置外键值即可。当然,Address
应该具有以下属性:
public User()
{
Addresses = new HashSet<Address>();
}
这对User
和UserID
被称为a,这是处理EF中关联的首选方法(正是因为它可以减少查询数量)。我会在Address
类中添加一个UserID
外键,然后我会这样做:
public class Address
{
public int ID { get; set; }
public string City { get; set; }
public string Street { get; set; }
public string Postcode { get; set; }
public int UserID { get; set; } // Set this property
public User User { get; set; }
}
无需检索用户或用户的现有地址
外键使实体框架更易于使用:
关系修复将同步导航属性:
public User()
{
Addresses = new HashSet<Address>();
}
var context = new TestDbContext();
context.Addresses.Add(new Address()
{
UserId = 1,
City = "City",
Street = "Street",
Postcode = "Postcode",
});
context.SaveChanges();