CSLA .NET

Vibrant discussion about CSLA .NET and using the framework to build great business applications.

Forum has moved

New location: CSLA .NET forum


CSLA .NET Resources:
  • CSLA .NET forum
  • CSLA .NET home page
  • Problems with Begin- / Cancel- / Apply-Edit operations

    rated by 0 users
    Answered (Verified) This post has 1 verified answer | 7 Replies | 1 Follower

    Not Ranked
    6 Posts
    DeepCore posted on Fri, Dec 10 2010 6:30 AM

    Hello community!

    I'm lost with the undo capabilities of CSLA. I have found several questions/answers dealing with the strange behavior of data binding under windows forms.

    But alas, I'm not using data binding at all in my test application. I'm using CSLA 3.8.4, C#, .NET 3.5SP1, VS2010, NHibernate with Fluent-NHibernate.

    I have built the following business objects:

    User object with 4 properties: UserID, FirstName, LastName and Role
    UserRole object with 2 properties: ID and Description.

    So far so good, I am able to persist these objects in the SQLite-DB. Smile

     

    Then I reload one user object from the DB, call .BeginEdit on it and assign another UserRole to the Role property ...

    Afterwards I call .CancelEdit, expecting my user object's role property would revert to it's state before the .BeginEdit call ...

    But that's not the case Crying

    What am I doing wrong ?

     

    Seasons greetings

    Philippe

    Answered (Verified) Verified Answer

    Top 10 Contributor
    2,279 Posts
    Answered (Verified) JonnyBee replied on Fri, Dec 10 2010 10:09 AM
    Verified by DeepCore

    The problem here is that you cannot change the object references.

    You may change the properties of parent and child -  and add/remove items in lists but you cannot change the object intance. The undo mechanism just will not be able to handle this properly.

    Jonny Bekkum, Norway CslaContrib Coordinator

    All Replies

    Not Ranked
    6 Posts

    As I've spent almost 2 days on this issue, I thought I may be lost in my code … so I reverted back to a simple test …

    But even this doesn't work to my expectations … the MyChild property doesn't revert back to 'InitialChild' after the call to root.CancelEdit …

     

        [Serializable]
        public class Root : BusinessBase<Root>
        {
            private static PropertyInfo<int> IdProperty = RegisterProperty<int>(typeof(Root), new PropertyInfo<int>("Id", "Id"));
            public int Id
            {
                get { return GetProperty<int>(IdProperty); }
                set { SetProperty<int>(IdProperty, value); }
            }

            private static PropertyInfo<string> NameProperty = RegisterProperty<string>(typeof(Root), new PropertyInfo<string>("Name", "Name"));
            public string Name
            {
                get { return GetProperty<string>(NameProperty); }
                set { SetProperty<string>(NameProperty, value); }
            }

            private static PropertyInfo<Child> ChildProperty = RegisterProperty<Child>(typeof(Root), new PropertyInfo<Child>("Children", "Children"));
            public Child MyChild
            {
                get
                {
                    if (!FieldManager.FieldExists(ChildProperty))
                        LoadProperty<Child>(ChildProperty, new Child());
                    return GetProperty<Child>(ChildProperty);
                }
                set { SetProperty(ChildProperty, value); }
            }

            protected override object GetIdValue()
            {
                return ReadProperty<int>(IdProperty);
            }
        }

     

        [Serializable]
        public class Child : BusinessBase<Child>
        {
            private static PropertyInfo<int> IdProperty = RegisterProperty<int>(typeof(Child), new PropertyInfo<int>("Id", "Id"));
            public int Id
            {
                get { return GetProperty<int>(IdProperty); }
                set { SetProperty<int>(IdProperty, value); }
            }

            private static PropertyInfo<string> NameProperty = RegisterProperty<string>(typeof(Child), new PropertyInfo<string>("Name", "Name"));
            public string Name
            {
                get { return GetProperty<string>(NameProperty); }
                set { SetProperty<string>(NameProperty, value); }
            }

          

            protected override object GetIdValue()
            {
                return ReadProperty<int>(IdProperty);
            }

            private static int _lastId;

            public Child()
            {
                LoadProperty<int>(IdProperty, System.Threading.Interlocked.Increment(ref _lastId));
                MarkAsChild();
            }      
        }

     

        class Program
        {
            static void Main(string[] args)
            {

                var root = new Root {Id = 1, Name = "TestRoot"};
                root.MyChild = new Child() { Name = "InitialChild" };

                root.BeginEdit();

                root.MyChild = new Child(){Name = "TestChild"};

                root.CancelEdit();
            }
        }

     

    Top 10 Contributor
    2,279 Posts
    Answered (Verified) JonnyBee replied on Fri, Dec 10 2010 10:09 AM
    Verified by DeepCore

    The problem here is that you cannot change the object references.

    You may change the properties of parent and child -  and add/remove items in lists but you cannot change the object intance. The undo mechanism just will not be able to handle this properly.

    Jonny Bekkum, Norway CslaContrib Coordinator

    Not Ranked
    6 Posts

    Takk JonnyBee Wink

    With your suggestion the undo works as I want it to work. But I've got another problem…

    The foreign key from the root to the child object in the DB doesn't get updated afterwards I assign new values to the child's properties.

     

    Philippe

    Top 10 Contributor
    2,279 Posts

    Hi,

    Is that after Save is called or when you assign values to the child's properties?

    Can you show some code sample?

     

    Jonny Bekkum, Norway CslaContrib Coordinator

    Not Ranked
    6 Posts

    Hi

    this is what I'm trying to do:

            static void Main(string[] args)
            {
                var userRoles = UserRoles.NewList();

                var roleOne = UserRole.NewRole();
                roleOne.Name = "RoleOne";
                roleOne.IsActive = false;

                var roleTwo = UserRole.NewRole();
                roleTwo.Name = "RoleTwo";
                roleTwo.IsActive = true;

                userRoles.Add(roleOne);
                userRoles.Add(roleTwo);
                userRoles.Save();

                //

                var testUser = User.NewUser();
                testUser.FirstName = "User";
                testUser.LastName = "Test";
                testUser.UserID = "testUser";
                testUser.Role = UserRole.GetByID(1);

                testUser = testUser.Save();

     

                // change role assigned to user
                var testUser2 = User.GetByID(1);
                testUser2.Role = UserRole.GetByID(2);
                testUser2 = testUser2.Save();
            }

    After 'testUser2.Save()' my user's record in the DB has the correct foreign key. The FK points now to role# 2.

    Now let's imagine that there is some UI to modify the assignement of the user role. And this is where I can't have the undo function.

    var testUser2 = User.GetByID(1);

    testUser2.BeginEdit();

    testUser2.Role = UserRole.GetByID(2);  // simulate an assignement from the UI

    testUser2.CancelEdit();

    This doesn't work.

     

    I suspect that I'm better off to fetch the record being edited again when a user wants to undo his modifications, don't I ?

     

    Philippe

    Not Ranked
    6 Posts

        [Serializable]
        public class User : NHibernateBusinessBase<User>
        {
            #region Business Methods

            private int _iD;

            private static readonly PropertyInfo<int> IDProperty = RegisterProperty<int>(p => p.ID);

            public virtual int ID
            {
                get { return GetProperty(IDProperty, _iD); }
                set { SetProperty(IDProperty, ref _iD, value); }
            }

            private string _userID;

            private static readonly PropertyInfo<string> UserIDProperty = RegisterProperty<string>(p => p.UserID, "User ID");

            public virtual string UserID
            {
                get { return GetProperty(UserIDProperty, _userID); }
                set { SetProperty(UserIDProperty, ref _userID, value); }
            }

            private string _firstName;

            private static readonly PropertyInfo<string> FirstNameProperty = RegisterProperty<string>(p => p.FirstName, "First name");

            public virtual string FirstName
            {
                get { return GetProperty(FirstNameProperty, _firstName); }
                set { SetProperty(FirstNameProperty, ref _firstName, value); }
            }

            private string _lastName;

            private static readonly PropertyInfo<string> LastNameProperty = RegisterProperty<string>(p => p.LastName, "Last name");

            public virtual string LastName
            {
                get { return GetProperty(LastNameProperty, _lastName); }
                set { SetProperty(LastNameProperty, ref _lastName, value); }
            }

            private UserRole _role;

            private static readonly PropertyInfo<UserRole> UserRoleProperty = RegisterProperty<UserRole>(p => p.Role,
                                                                                                         "User role",
                                                                                                         UserRole.NewRole(),
                                                                                                         RelationshipTypes.
                                                                                                             Child);

            public virtual UserRole Role
            {
                get { return GetProperty(UserRoleProperty, _role); }
                set { SetProperty(UserRoleProperty, ref _role, value); }
            }

            #endregion

            #region Business Rules

            protected override void AddBusinessRules()
            {
                ValidationRules.AddRule(CommonRules.StringRequired, new RuleArgs(UserIDProperty));
                ValidationRules.AddRule(CommonRules.StringRequired, new RuleArgs(FirstNameProperty));
                ValidationRules.AddRule(CommonRules.StringRequired, new RuleArgs(LastNameProperty));
            }
            #endregion


            #region Authorization Rules

            #endregion


            #region Factory Methods

            protected User()
            {

            }

            public static User GetByID(int id)
            {
                return DataPortal.Fetch<User>(new SingleCriteria<User, int>(id));
            }

            public static User NewUser()
            {
                return DataPortal.Create<User>();
            }
            #endregion


            #region Data Access

            #endregion


            #region Overrides

            public override string ToString()
            {
                return string.Format("{0} {1}", FirstName, LastName);
            }


            protected override object GetUniqueIdentifier(object businessCriteria)
            {
                return ((SingleCriteria<User, int>)businessCriteria).Value;
            }
            #endregion

        }

    Not Ranked
    6 Posts

        [Serializable]
        public class UserRole : NHibernateBusinessBase<UserRole>
        {
            #region Business Methods

            private int _iD;

            private static readonly PropertyInfo<int> IDProperty = RegisterProperty<int>(p => p.ID);

            public virtual int ID
            {
                get { return GetProperty(IDProperty, _iD); }
                set { SetProperty(IDProperty, ref _iD, value); }
            }

            private string _name;

            private static readonly PropertyInfo<string> NameProperty = RegisterProperty<string>(p => p.Name, "Role name", String.Empty);

            public virtual string Name
            {
                get { return GetProperty(NameProperty, _name); }
                set { SetProperty(NameProperty, ref _name, value); }
            }

            private bool _isActive;

            private static readonly PropertyInfo<bool> IsActiveProperty = RegisterProperty<bool>(p => p.IsActive, "State", false);

            public virtual bool IsActive
            {
                get { return GetProperty(IsActiveProperty, _isActive); }
                set { SetProperty(IsActiveProperty, ref _isActive, value); }
            }

            #endregion


            #region Business Rules

            protected override void AddBusinessRules()
            {
                ValidationRules.AddRule(CommonRules.StringRequired, NameProperty, 0);
            }
            #endregion


            #region Authorization Rules

            #endregion


            #region Factory Methods


            public static UserRole GetByID(int temp)
            {
                return DataPortal.Fetch<UserRole>(new SingleCriteria<UserRole, int>(temp));
            }

            public static UserRole NewRole()
            {
                return DataPortal.CreateChild<UserRole>();
            }

            protected UserRole()
            {
            }
            #endregion


            #region Data Access

            #endregion


            #region Overrides

            public override string ToString()
            {
                return Name;
            }

            protected internal override void Init()
            {
                base.Init();

                MarkAsChild();
            }

            protected override object GetUniqueIdentifier(object businessCriteria)
            {
                return ((SingleCriteria<UserRole, int>)businessCriteria).Value;
            }
            #endregion

        }

    Page 1 of 1 (8 items) | RSS

    Copyright (c) 2006-2014 Marimer LLC. All rights reserved.
    Email admin@lhotka.net for support.
    Powered by Community Server (Non-Commercial Edition), by Telligent Systems