Question Summary:
Why would a "Multiplicity constraint violated" be able to be worked around by the introduction of the following line of code?
var numModifiedObjects =createdObject.ObjectSpace.ModifiedObjects.Count; Is there a setting that would make the work around unnecessary?
Background of the problem followed by the work around:
In my winforms xaf, EF6.2 Code First project I have the following business object which is self referencing.
[NavigationItem("Main")] public class H2Category : IHCategory { public H2Category() { Children = new BindingList<H2Category>(); } [Browsable(false)] public Int32 ID { get; protected set; } public String Name { get; set; } public H2Category Parent { get; set; } public virtual IList<H2Category> Children { get; set; } [NotMapped, Browsable(false), RuleFromBoolProperty("H2CategoryCircularReferences", DefaultContexts.Save, "Circular refrerence detected. To correct this error, set the Parent property to another value.", UsedProperties = "Parent")] public Boolean IsValid { get { H2Category currentObj = Parent; while (currentObj != null) { if (currentObj == this) { return false; } currentObj = currentObj.Parent; } return true; } } IBindingList ITreeNode.Children => Children as IBindingList; ITreeNode IHCategory.Parent { get => Parent as IHCategory; set => Parent = value as H2Category; } ITreeNode ITreeNode.Parent => Parent as ITreeNode; } and in the dbContext OnModelCreating I use
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>(); modelBuilder.Entity<H2Category>().HasMany(x => x.Children).WithOptional(x => x.Parent); Parent_Id);
The database looks correct in the SQL Server Object Explorer 
and the data looks correct.
In the XAF Treeview, when the user adds a child record, I want the new child's parent to be set to the current record.
To do this I am using a NewObjectViewController
public partial class H2CategoryController : ViewController { private NewObjectViewController controller; public H2CategoryController() { InitializeComponent(); TargetObjectType = typeof(H2Category); } protected override void OnActivated() { controller = Frame.GetController<NewObjectViewController>(); controller.ObjectCreated += controller_ObjectCreated; base.OnActivated(); } private void controller_ObjectCreated(object sender, ObjectCreatedEventArgs e) { var createdObject = e.CreatedObject as H2Category; var currentObject = View.CurrentObject as H2Category; // inspection here shows that currentObject and createdObject are different but they have the same proxy var s = $"created object Id is {createdObject.ID} current object id is {currentObject.ID}"; Console.WriteLine(s); var propertyCollectionSource = (View as ListView)?.CollectionSource as PropertyCollectionSource; if (!(propertyCollectionSource?.MasterObject is H2Category master)) return; createdObject.Parent = master; createdObject.Name = "t"; master.Children.Add(createdObject); Console.WriteLine(master.ID); } protected override void OnDeactivated() { controller.ObjectCreated += controller_ObjectCreated; base.OnDeactivated(); } } As soon as the user starts typing into the new record the following error appears
Multiplicity constraint violated. The role 'H2Category_Children_Source' of the relationship 'SBD.GL.Module.BusinessObjects.H2Category_Children' has multiplicity 1 or 0..1. at System.Data.Entity.Core.Objects.EntityEntry.AddDetectedRelationship[T](Dictionary`2 relationships, T relatedObject, RelatedEnd relatedEnd) at System.Data.Entity.Core.Objects.EntityEntry.AddRelationshipDetectedByGraph(Dictionary`2 relationships, Object relatedObject, RelatedEnd relatedEndFrom, Boolean verifyForAdd) at System.Data.Entity.Core.Objects.EntityEntry.DetectChangesInRelationshipsOfSingleEntity() at System.Data.Entity.Core.Objects.ObjectStateManager.DetectChangesInNavigationProperties(IList`1 entries) at System.Data.Entity.Core.Objects.ObjectStateManager.DetectChanges() at System.Data.Entity.Core.Objects.ObjectContext.DetectChanges() at DevExpress.ExpressApp.EF.EFObjectSpace.DetectChanges() at DevExpress.ExpressApp.EF.EFObjectSpace.GetModifiedObjects() at DevExpress.ExpressApp.EF.EFObjectSpace.get_ModifiedObjects() at DevExpress.ExpressApp.Win.SystemModule.CustomCollectModifiedObjectsEventArgs.CollectModifiedObjects(Boolean checkObjectSpaceIsModified) at DevExpress.ExpressApp.Win.SystemModule.LockController.GetModifiedObjects() at DevExpress.ExpressApp.Win.SystemModule.LockController.CheckLocking(LockController controller) at DevExpress.ExpressApp.Win.SystemModule.LockController.CheckLocking(Object obj) at DevExpress.ExpressApp.Win.SystemModule.LockController.ViewObjectSpace_ObjectChanged(Object sender, ObjectChangedEventArgs e) at System.EventHandler`1.Invoke(Object sender, TEventArgs e) at DevExpress.ExpressApp.BaseObjectSpace.OnObjectChanged(ObjectChangedEventArgs args) at DevExpress.ExpressApp.EF.EFObjectSpace.SetModified(Object obj, ObjectChangedEventArgs args) at DevExpress.ExpressApp.BaseObjectSpace.SetModified(Object obj, IMemberInfo memberInfo) at DevExpress.ExpressApp.DetailView.Editor_ControlValueChanged(Object sender, EventArgs e) at System.EventHandler.Invoke(Object sender, EventArgs e) at DevExpress.ExpressApp.Editors.PropertyEditor.OnControlValueChanged() at DevExpress.ExpressApp.Win.Editors.DXPropertyEditor.Editor_EditValueChanged(Object sender, EventArgs e) at System.EventHandler.Invoke(Object sender, EventArgs e) at DevExpress.XtraEditors.Repository.RepositoryItem.RaiseEditValueChangedCore(EventArgs e) at DevExpress.XtraEditors.Repository.RepositoryItem.RaiseEditValueChanged(EventArgs e) at DevExpress.XtraEditors.BaseEdit.RaiseEditValueChanged() at DevExpress.XtraEditors.BaseEdit.OnEditValueChanged() at DevExpress.XtraEditors.TextEdit.OnEditValueChanged() at DevExpress.XtraEditors.BaseEdit.OnEditValueChanging(ChangingEventArgs e) at DevExpress.XtraEditors.TextEdit.OnEditValueChanging(ChangingEventArgs e) at DevExpress.XtraEditors.BaseEdit.set_EditValue(Object value) at DevExpress.XtraEditors.TextEdit.OnMaskBox_ValueChanged(Object sender, EventArgs e) at DevExpress.XtraEditors.Mask.MaskBox.RaiseEditTextChanged() at DevExpress.XtraEditors.Mask.MaskBox.MaskStrategy.SimpleStrategy.DoAfterTextChanged(EventArgs e) at DevExpress.XtraEditors.Mask.MaskBox.OnTextChanged(EventArgs e) at System.Windows.Forms.TextBoxBase.WmReflectCommand(Message& m) at System.Windows.Forms.TextBoxBase.WndProc(Message& m) at System.Windows.Forms.TextBox.WndProc(Message& m) at DevExpress.XtraEditors.Mask.MaskBox.BaseWndProc(Message& m) at DevExpress.XtraEditors.Mask.MaskBox.MaskStrategy.SimpleStrategy.DoWndProc(Message& m) at DevExpress.XtraEditors.Mask.MaskBox.WndProc(Message& m) at DevExpress.XtraEditors.TextBoxMaskBox.WndProc(Message& msg) at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) I note that the debug values look correct when I set the parent 
But am confused that all the H2Category objects have the same proxy value.
I have asked about the issue at Dev Express but ask here as well as it is Entity Framework related.
[Update -Work Around]
I added the IObjectSpaceLink interface to the business object. This exposes the ObjectSpace as a property of the business object.
When I put a break in the controller_ObjectCreated method I was able to see that the ModifiedObjects property was showing an error
I found that if I assign createdObject.ObjectSpace.ModifiedObjects.Count to a variable then the problem does not occur.
private void controller_ObjectCreated(object sender, ObjectCreatedEventArgs e) { var createdObject = e.CreatedObject as H2Category; var numModifiedObjects =createdObject.ObjectSpace.ModifiedObjects.Count; var currentObject = View.CurrentObject as H2Category; var s = $"created object Id is {createdObject.ID} current object id is {currentObject.ID}"; var propertyCollectionSource = (View as ListView)?.CollectionSource as PropertyCollectionSource; if (!(propertyCollectionSource?.MasterObject is H2Category master)) return; var m = e.ObjectSpace.GetObject(master); createdObject.Parent = m; createdObject.Name = "t"; m.Children.Add(createdObject); numModifiedObjects = createdObject.ObjectSpace.ModifiedObjects.Count; Console.WriteLine(master.ID); } I tried disabling Proxy creation but it did not help.



