NHibernate - Session.Merge导致NHibernate.LazyInitializationException:非法访问加载集合

时间:2012-10-24 06:59:58

标签: nhibernate session fluent-nhibernate merge observablecollection

尝试使用Merge保存项目时出现此错误。该项目有一个袋子(儿童)我喜欢可绑定,因此转换为带有自定义访问器的ObservableCollection。

这是映射:

RootItemMap() {
        Id(x => x.Id); 
        Map(x => x.Description);
        HasMany<ChildItem>(x => x.Children).Access.Using<ObservableAccessor<ChildItem>>().KeyColumn("RootId").Cascade.All();

}

这在客户端上工作正常。我可以添加和删除项目,UI响应很好。但是当我尝试使用session.Merge保存更改时,我得到了上述异常。

自定义访问者:

public class ObservableAccessor<T> : IPropertyAccessor
{
    #region Setter      

    private class ObservableGetterSetter : IGetter, ISetter
    {
        private PropertyInfo _property;

        public ObservableGetterSetter(PropertyInfo property)
        {
            if (property == null) throw new ArgumentNullException("property");
            _property = property;
        }

        public void Set(object target, object value)
        {
            var collection = new ObservableCollection<T>((IList<T>)value);
            _property.SetValue(target, collection, null);
        }

        public object Get(object target)
        {
            var list = _property.GetValue(target, null) as IList<T>;
            return list;
        }

        public object GetForInsert(object owner, IDictionary mergeMap, ISessionImplementor session)
        {
            return Get(owner);
        }

        public Type ReturnType
        {
            get { return typeof (IList<T>); }
        }

        public string PropertyName
        {
            get { return _property.Name; }
        }

        public MethodInfo Method
        {
            get { return null; }
        }
    }

    #endregion

    public IGetter GetGetter(Type theClass, string propertyName)
    {
        return new ObservableGetterSetter(theClass.GetProperty(propertyName));
    }

    public ISetter GetSetter(Type theClass, string propertyName)
    {
        return new ObservableGetterSetter(theClass.GetProperty(propertyName));
    }

    public bool CanAccessThroughReflectionOptimizer
    {
        get { return false; }
    }

有什么想法吗?如果我在Set方法中添加Try-Catch,这可以正常工作。

这是一个说明错误的测试类(ThenItCanBeSavedWithMerge导致错误):

namespace MergeProblem.Tests
{
    [TestFixture]
    public class WhenWorkingWithRootItemWithChildren
    {
        private int _id;
        private RootItem _root;

        [TestFixtureSetUp]
        public void AddRootWithChildrenToDatabase()
        {
            var root = new RootItem();
            root.Description = "My decription";
            IList<ChildItem> children = new ObservableCollection<ChildItem>() { new ChildItem() { Description = "First child" }, new ChildItem() { Description = "Second child"}};
            root.Children = children;

            using (var session = SessionManager.GetSession())
            {
                using (var tx = session.BeginTransaction())
                {
                    session.SaveOrUpdate(root);
                    tx.Commit();
                }

                _id = root.Id;
                _root = root;
            }
        }

        [Test]
        public void ThenItCanBeAccessed()
        {
            using (var session = SessionManager.GetSession())
            {
                var root = session.Get<RootItem>(_id);

                Assert.IsNotNull(root, "Root is null");
                Assert.AreEqual(_id, root.Id, "Id incorrect");
                Assert.IsNotNull(root.Children, "Children is null");
                Assert.AreEqual(2, root.Children.Count);
            }
        }

        [Test]
        public void ThenTheChildrenCollectionIsObservable()
        {          
            Assert.That(_root.Children, Is.InstanceOf(typeof(INotifyCollectionChanged)), "We want the collection to be observable");
        } 

        [Test]
        public void ThenItCanBeSavedWithMerge()
        {
            var newChild = new ChildItem() { Description = "New child" };
            _root.Children.Add(newChild);

            using (var session = SessionManager.GetSession())
            {
                using (var tx = session.BeginTransaction())
                {
                    _root = session.Merge(_root);
                    tx.Commit();
                }
            }

            Assert.AreEqual(3, _root.Children.Count);
        }
    }
}

0 个答案:

没有答案