0

有点好奇。我有一个 User 对象,其中包含一个包,每个 UserPhoto、UserMatchInterest、UserPreference 对象。我已经为包中的每个项目提供了对父用户的引用,并且使用 nhibernate 我已经对两种方式的映射进行了排序,因此当您第一次创建用户对象时,它会自动创建 UserPhoto、UserMatchInterest 和 UserPreference 对象收集袋,将 UserId 设置为父 User 对象,效果很好。

例如,UserPhoto 表有一个 PhotoId PK 列和一个 UserId FK 列。UserPhoto 对象具有 PhotoId 属性和 User 属性(不是 UserId),因此它不持有 UserId,而是持有对父级的引用并根据用户 PK 填充 DB 列。

我遇到的问题是当我想一次性更新用户对象时。User 对象的其余部分更新正常,但是当涉及到照片时,它会在数据库中创建新照片。我可以理解为什么,因为它们根本没有链接到作为 ASP.NET 网站可以接受的以前的照片会话对象,所以我将处理分离的对象。但它留下了旧的。因此,如果您有照片 ID 1 和 2,且 UserId=1。更新后,您将拥有 UserId=1 的照片 1、2、3 和 4。我想要的是删除照片 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);

在存储库上引发错误。DeleteItems(interests.ToList()); 行,第一个删除通过正常 - 尽管它都在事务中。

我的问题是我是否以正确的方式更新数据库中的对象,该对象还包含需要更新的其他对象包?如果不手动设置 ID,我看不到任何更新现有照片对象的方法 - 并且用户可能已经替换了所有照片或添加/删除了所有照片,因此删除现有照片并重新添加新照片可能更干净,但是如何删除现有照片那些没有得到这个级联错误的?

4

1 回答 1

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 将自动删除不再属于集合的所有子项

于 2012-11-29T13:23:17.100 回答