使用具有一对多关系的实体列表的属性更新数据库上的实体
本文关键字:实体 列表 属性 数据库 更新 一对多 关系 | 更新日期: 2023-09-27 18:36:18
我将组成一些更简单的实体来更好地理解:
public class Room
{
[Required]
public int Id { get; set; }
[Required]
public int Name { get; set; }
[Required]
[Column("House_Id")]
public int HouseId { get; set; }
public virtual House House { get; set; }
}
public class House
{
[Required]
public int Id{ get; set; }
public string Name { get; set; }
public virtual ICollection<Room> Rooms { get; set; }
}
现在,假设我有一个房屋实体,数据库中有 4 个与之相关的房间。我想更新房子并删除它的 2 个房间。顺便说一句,我正在使用 Asp.Net MVC4。
var house = HouseRepository.Get(id);
house.Name = model.Name; // Some string
house.Name = model.Rooms; // ICollection<Room> from view with 2 rooms in it, cuz user deleted other two in view
HouseRepository.SaveChanges();
return house;
发生的情况是,我收到错误说:操作失败:无法更改关系,因为一个或多个外键属性不可为空。对关系进行更改时,相关的外键属性将设置为 null 值。如果外键不支持空值,则必须定义新关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象。
我需要找到一个解决方案,如何从数据库中删除不相关的房间。我应该在何时何地这样做?我已经尝试了一些东西,但现在即使我正在添加房间,我也会收到该错误。
是否有任何简单的方法可以告诉 EF 它应该自行删除这些房间?
仅
当使用标识关系时,EF 才能自动删除孤立项。您需要为 Room
对象定义一个组合键,该键由 Id
和 HouseID
组成。
modelbuilder.Entity<Room>()
.HasKey(o => new { o.ID, o.HouseId });
modelbuilder.Entity<Room>()
.Property(o => o.ID)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
使用此配置,EF 知道,当您从 Rooms
集合中删除房间对象时,也可以安全地删除数据库的房间。
删除您不再需要单独使用的房间,以将其从模型中显式删除 - 相当于以下内容:
foreach(Room room in house.Rooms.ToList())
{
if(model.Rooms.FirstOrDefault(x=>x.Id == room.Id) == null)
dbContext.Rooms.Remove(room); //assumes the room is attached to your context, you may need to do a get
}
假设您设置的 1 栋房屋当前有 4 个与之关联的房间,这应该可以工作:
var db = new TestContext();
var house = db.Houses.Include("Rooms").First();
// Grab rooms 2 & 3 for removal
var roomsToRemove = house.Rooms.OrderBy(r => r.Id).Skip(1).Take(2).ToList();
roomsToRemove.ForEach(r => db.Rooms.Remove(r));
db.SaveChanges();