有点好奇。我有一个User对象,其中包含UserPhoto,UserMatchInterest,UserPreference对象的每个包。我已经为包中的每个项目提供了对父用户的引用,并且使用nhibernate我已经对双向映射进行了排序,这样当您第一次创建用户对象时,它会自动创建UserPhoto,UserMatchInterest和UserPreference对象。收集袋,将UserId设置为父User对象,工作正常。
例如,UserPhoto表具有PhotoId PK列和UserId FK列。 UserPhoto对象具有PhotoId属性和User属性(不是UserId),因此它不保存UserId,而是保存对父级的引用,并根据Users PK填充DB列。
我遇到的问题是当我想一次性更新User对象时。 User对象的其余部分更新正常,但是当涉及到照片时,它会在数据库中创建新照片。我可以理解为什么,因为它们根本没有链接到以前的照片会话对象,可以接受作为ASP.NET网站,我将处理分离的对象。但它留下了旧的。所以如果你有照片ID 1& 2,UserId = 1。更新后,您将获得照片1,2,3& 4,UserId = 1。我想要的是照片1& 2删除然后插入3& 4而不是。
我曾尝试将它们作为集合独立检索并首先在事务中删除它们,但我收到了消息
Message = "deleted object would be re-saved by cascade (remove deleted object from associations)
要删除的代码如下
// First delete existing photos, interests and preferences
var photos = from row in repository.GetItemsAsQuery<UserPhoto>()
where row.User.UserId == user.UserId
select row;
repository.DeleteItems(photos.ToList());
var interests = from row in repository.GetItemsAsQuery<UserMatchInterest>()
where row.User.UserId == user.UserId
select row;
repository.DeleteItems(interests.ToList());
var preferences = from row in repository.GetItemsAsQuery<UserPreference>()
where row.User.UserId == user.UserId
select row;
repository.DeleteItems(preferences.ToList());
// Now update the user object and re-add the above linked items
repository.UpdateItem(user);
在repository.DeleteItems(interests.ToList())上抛出错误;第一行删除通过正常 - 尽管它都在一个事务中。
我的问题是我是否正确地更新数据库中的对象以及需要更新的其他对象?我没有看到任何更新现有照片对象的方法而无需手动设置ID - 用户可能已经替换了所有照片或添加/删除了所以删除现有照片并重新添加新照片可能更干净,但如何删除现有照片哪些没有得到这个级联错误?
答案 0 :(得分:0)
从您的描述我设想以下类
public class User
{
public virtual int Id { get; set; }
public virtual ICollection<Photo> Photos { get; private set; }
}
public class Photo
{
public User Parent { get; set; }
public virtual string Name { get; set; }
public virtual byte[] Data { get; set; }
}
然后映射看起来像
public class UserMap : ClassMap<User>
{
public UserMap()
{
Id(x => x.Id);
HasMany(x => x.Photos)
.AsSet() // no duplicate entries, allows NH to optimise some things
.Cascade.AllDeleteOrphan()
.Component(c =>
{
c.ParentReference(x => x.Parent);
c.Map(x => x.Name);
c.Map(x => x.Data);
});
}
}
注意:Cascade.AllDeleteOrphan将自动删除所有不属于该集合的子项