Нарушение множественности нарушено (в XAF, когда не создан доступ к selectedObject.ObjectSpace.ModifiedObjects.Count.) - PullRequest
0 голосов
/ 07 января 2019

Вопрос Резюме:

Почему можно "обойти ограничение множественности", введя следующую строку кода?

var numModifiedObjects =createdObject.ObjectSpace.ModifiedObjects.Count;

Есть ли настройка, которая сделает ненужным обходной путь?

Предпосылки проблемы с последующим обходом:

В моем winforms xaf, проекте EF6.2 Code First, у меня есть следующий бизнес-объект, который сам ссылается.

[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;
}

и в dbContext OnModelCreating я использую

   modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

   modelBuilder.Entity<H2Category>().HasMany(x => x.Children).WithOptional(x => x.Parent);

PARENT_ID);

База данных выглядит правильно в проводнике объектов SQL Server the SQL Server Object Explorer

и данные выглядят правильно.

data table

В XAF Treeview, когда пользователь добавляет дочернюю запись, я хочу, чтобы родитель нового дочернего элемента был установлен на текущую запись.

Для этого я использую 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();
    }
}

Как только пользователь начинает вводить новую запись, появляется следующая ошибка

    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)

error message

Замечу, что значения отладки выглядят корректно, когда я устанавливаю родителя debug values

Но я смущен тем, что все объекты H2Category имеют одинаковое значение прокси.

Я спрашивал о проблеме на Dev Express , но спрашивайте здесь также, как это связано с Entity Framework.

[Обновление - Работа вокруг]

Я добавил интерфейс IObjectSpaceLink к бизнес-объекту. Это предоставляет ObjectSpace как свойство бизнес-объекта.

Когда я поставил разрыв в методе controller_ObjectCreated, я смог увидеть, что свойство ModifiedObjects показывает ошибку

ModifiedObjects error

Я обнаружил, что если я назначу переменную selectedObject.ObjectSpace.ModifiedObjects.Count переменной, проблема не возникает.

       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);

    }

Я пытался отключить создание прокси, но это не помогло.

exception

1 Ответ

0 голосов
/ 14 января 2019

От ответа поддержки Dev Express .

В моем проекте отношения работают некорректно из-за ошибки в моем классе H2Category. Свойство Parent должно быть объявлено виртуальным.

Кроме того, мой ICategoryController конфликтует со встроенным TreeNodeController. Этот контроллер также подписывается на событие NewObjectViewController.ObjectCreated и связывает вновь созданный объект ITreeNode с родительским узлом, выбранным в представлении списка источников. По умолчанию объекты связываются при сохранении изменений. Чтобы связать новый объект сразу после создания, установите для свойства NewObjectViewController.LinkNewObjectToParentImmediately значение true.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...