尝试使用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);
}
}
}