public void EntityConflict_Resolve()
        {
            TestEntityContainer ec = new TestEntityContainer();
            EntitySet<Product> set = ec.Products;
            Product current = new Product { ProductID = 1, Color = "Red", ProductNumber = "1234" };
            set.LoadEntity(current);
            
            // create a conflict and resolve
            current.Color += "X";
            Product store = new Product { ProductID = 1, Color = "Red", ProductNumber = "4321" };
            EntityConflict conflict = new EntityConflict(current, store, new string[] { "ProductNumber" }, false);
            current.EntityConflict = conflict;
            Assert.AreEqual(EntityState.Modified, current.EntityState);
            var originalState = conflict.OriginalEntity.ExtractState();
            Assert.IsTrue((string)originalState["Color"] == "Red" && (string)originalState["ProductNumber"] == "1234");

            conflict.Resolve();

            // verify that calling Resolve multiple
            // times is a no-op
            conflict.Resolve();
            conflict.Resolve();

            // resolve should update the original state
            originalState = current.GetOriginal().ExtractState();
            Assert.IsTrue((string)originalState["Color"] == "Red" && (string)originalState["ProductNumber"] == "4321");

            // current state should not be modified
            Assert.AreEqual("RedX", current.Color);
            Assert.AreEqual("1234", current.ProductNumber);
            
            // the conflict should be cleared out
            Assert.IsNull(current.EntityConflict);
        }
        public void Inherit_Run_Entity_SpecializedAssociation()
        {
            TestEntityContainer container = new TestEntityContainer();
            var cities = container.LoadEntities(_citiesWithInfo).OfType<CityWithInfo>();

            var redmond = cities.Single(c => c.Name == "Redmond");
            Assert.AreEqual(3, redmond.ZipCodes.Count);
            Assert.AreEqual(1, redmond.ZipCodesWithInfo.Count);
            Assert.AreEqual("Microsoft", redmond.ZipCodesWithInfo.Single().Info);
        }
        public void Inherit_Run_Entity_SpecializedAssociation()
        {
            TestEntityContainer container = new TestEntityContainer();
            var cities = container.LoadEntities(_citiesWithInfo).OfType <CityWithInfo>();

            var redmond = cities.Single(c => c.Name == "Redmond");

            Assert.AreEqual(3, redmond.ZipCodes.Count);
            Assert.AreEqual(1, redmond.ZipCodesWithInfo.Count);
            Assert.AreEqual("Microsoft", redmond.ZipCodesWithInfo.Single().Info);
        }
        public void Inherit_Run_Entity_ReadOnly()
        {
            TestEntityContainer container = new TestEntityContainer();

            container.LoadEntities(_citiesWithInfo);

            Assert.IsFalse(_citiesWithInfo[0].IsReadOnly);
            _citiesWithInfo[0].SetCityInfo("new stuff");
            Assert.IsTrue(_citiesWithInfo[0].IsReadOnly);

            ((System.ComponentModel.IRevertibleChangeTracking)_cities[0]).RejectChanges();

            Assert.IsFalse(_citiesWithInfo[1].IsReadOnly);
        }
        public void Entity_InvokeOnLoaded()
        {
            TestEntityContainer container = new TestEntityContainer();
            container.LoadEntities(_cities);
            Assert.AreEqual(EntityState.Unmodified, _cities[0].EntityState);
            Assert.AreEqual(0, _cities[0].EntityActions.Count());
            Assert.IsTrue(_cities[0].CanInvokeAction(_assignCityZone.Name));

            // verify invoke on a new entity succeeds and subsequent CanInvoke returns false
            _cities[0].InvokeAction(_assignCityZone.Name, _assignCityZone.Parameters.ToArray<object>());
            Assert.AreEqual(1, _cities[0].EntityActions.Count());
            Assert.AreEqual(EntityState.Modified, _cities[0].EntityState);
            Assert.AreEqual<string>(_assignCityZone.Name, _cities[0].EntityActions.Single().Name);
            Assert.AreEqual<int>(_assignCityZone.Parameters.Count(), _cities[0].EntityActions.Single().Parameters.Count());
            Assert.IsFalse(_cities[0].CanInvokeAction(_assignCityZone.Name));
        }
        public void Inherit_Run_Entity_InvokeOnLoaded()
        {
            TestEntityContainer container = new TestEntityContainer();

            container.LoadEntities(_citiesWithInfo);
            Assert.AreEqual(EntityState.Unmodified, _citiesWithInfo[0].EntityState);
            Assert.AreEqual(0, _citiesWithInfo[0].EntityActions.Count());
            Assert.IsTrue(_citiesWithInfo[0].CanInvokeAction(_setCityInfo.Name));

            // verify invoke on a new entity succeeds and subsequent CanInvoke returns false
            _citiesWithInfo[0].InvokeAction(_setCityInfo.Name, _setCityInfo.Parameters.ToArray <object>());
            Assert.AreEqual(1, _citiesWithInfo[0].EntityActions.Count());
            Assert.AreEqual(EntityState.Modified, _citiesWithInfo[0].EntityState);
            Assert.AreEqual <string>(_setCityInfo.Name, _citiesWithInfo[0].EntityActions.Single().Name);
            Assert.AreEqual <int>(_setCityInfo.Parameters.Count(), _citiesWithInfo[0].EntityActions.Single().Parameters.Count());
            Assert.IsFalse(_citiesWithInfo[0].CanInvokeAction(_setCityInfo.Name));
        }
        public void Inherit_Run_Entity_Invoke_Illegal_EntityAction()
        {
            TestEntityContainer container = new TestEntityContainer();

            container.LoadEntities(_rootCities);
            var invocableCity = _rootCities[0];

            Assert.IsNotNull(invocableCity);

            // verify calling Invoke throws InvalidOperationException and the invocation list remains the same
            ExceptionHelper.ExpectException <MissingMethodException>(delegate
            {
                invocableCity.InvokeAction(_setCityInfo.Name, _setCityInfo.Parameters.ToArray());
            }, string.Format(Resource.ValidationUtilities_MethodNotFound, "Cities.City", _setCityInfo.Name, _setCityInfo.Parameters.Count(), "'System.String'"));

            Assert.AreEqual(EntityState.Unmodified, _rootCities[0].EntityState);
        }
        public void Entity_ReadOnly()
        {
            TestEntityContainer container = new TestEntityContainer();
            container.LoadEntities(_cities);

            Assert.IsFalse(_cities[0].IsReadOnly);
            _cities[0].AssignCityZone(_assignCityZone.Name);
            Assert.IsTrue(_cities[0].IsReadOnly);

            Assert.IsFalse(_cities[1].IsReadOnly);
            _cities[1].CountyName += "X";
            _cities[1].AssignCityZone(_assignCityZone.Name);
            Assert.IsTrue(_cities[1].IsReadOnly);

            ((System.ComponentModel.IRevertibleChangeTracking)_cities[1]).RejectChanges();

            Assert.IsFalse(_cities[1].IsReadOnly);
        }
Ejemplo n.º 9
0
        public void EntityConflict_Resolve()
        {
            TestEntityContainer ec      = new TestEntityContainer();
            EntitySet <Product> set     = ec.Products;
            Product             current = new Product {
                ProductID = 1, Color = "Red", ProductNumber = "1234"
            };

            set.LoadEntity(current);

            // create a conflict and resolve
            current.Color += "X";
            Product store = new Product {
                ProductID = 1, Color = "Red", ProductNumber = "4321"
            };
            EntityConflict conflict = new EntityConflict(current, store, new string[] { "ProductNumber" }, false);

            current.EntityConflict = conflict;
            Assert.AreEqual(EntityState.Modified, current.EntityState);
            var originalState = conflict.OriginalEntity.ExtractState();

            Assert.IsTrue((string)originalState["Color"] == "Red" && (string)originalState["ProductNumber"] == "1234");

            conflict.Resolve();

            // verify that calling Resolve multiple
            // times is a no-op
            conflict.Resolve();
            conflict.Resolve();

            // resolve should update the original state
            originalState = current.GetOriginal().ExtractState();
            Assert.IsTrue((string)originalState["Color"] == "Red" && (string)originalState["ProductNumber"] == "4321");

            // current state should not be modified
            Assert.AreEqual("RedX", current.Color);
            Assert.AreEqual("1234", current.ProductNumber);

            // the conflict should be cleared out
            Assert.IsNull(current.EntityConflict);
        }
        public void Entity_InvalidNameToInvoke()
        {
            TestEntityContainer container = new TestEntityContainer();
            container.LoadEntities(_cities);

            // call Invoke with name=empty string
            ExceptionHelper.ExpectArgumentException(delegate
            {
                _cities[0].InvokeAction("");
            }, string.Format(CultureInfo.CurrentCulture, Resource.Parameter_NullOrEmpty, "actionName"));

            // call invoke with name=null
            ExceptionHelper.ExpectArgumentException(delegate
            {
                _cities[0].InvokeAction(null);
            }, string.Format(CultureInfo.CurrentCulture, Resource.Parameter_NullOrEmpty, "actionName"));

            // The following is commented since the product currently ignores the name attribute as
            // only one domain method is allowed for an entity.
            //// call CanInvoke with name=emtpy string
            //ExceptionHelper.ExpectArgumentException(delegate
            //{
            //    _cities[0].CanInvoke("");
            //}, string.Format(CultureInfo.CurrentCulture, Resource.Parameter_NullOrEmpty, "actionName"));

            //// call CanInvoke with name=null
            //ExceptionHelper.ExpectArgumentException(delegate
            //{
            //    _cities[0].CanInvoke(null);
            //}, string.Format(CultureInfo.CurrentCulture, Resource.Parameter_NullOrEmpty, "actionName"));

            Assert.AreEqual(EntityState.Unmodified, _cities[0].EntityState);
        }
        public void DomainClient_SubmitWithNullInvocation()
        {
            TestEntityContainer container = new TestEntityContainer();

            //TODO: find a better way to not hardcode the list of known types
            WebDomainClient<CityDomainContext.ICityDomainServiceContract> client = new WebDomainClient<CityDomainContext.ICityDomainServiceContract>(TestURIs.Cities)
            {
                EntityTypes = new Type[] { typeof(City), typeof(ChangeSetEntry), typeof(EntityOperationType) }
            };
            List<Entity> emptyList = new List<Entity>();
            List<Entity> modifiedEntities = new List<Entity>();

            // invoke domain methods on a few entities
            container.LoadEntities(_cities);
            _cities[1].AssignCityZone(_assignCityZone.Parameters.First().ToString());

            // submit changeset with hand-crafted entities: valid invocation and null invocation
            modifiedEntities.Add(_cities[0]);
            modifiedEntities.Add(_cities[1]);
            modifiedEntities.Add(_cities[2]);
            Assert.AreEqual(EntityState.Modified, _cities[1].EntityState);
            EntityChangeSet changeset = new EntityChangeSet(emptyList.AsReadOnly(), modifiedEntities.AsReadOnly(), emptyList.AsReadOnly());
            SubmitCompletedResult submitResults = null;
            client.BeginSubmit(
                changeset,
                delegate(IAsyncResult asyncResult)
                {
                    submitResults = client.EndSubmit(asyncResult);
                },
                null
            );

            // wait for submit to complete
            EnqueueConditional(() => submitResults != null);
            EnqueueCallback(delegate
            {
                Assert.AreEqual(1, submitResults.Results.Count());
                Assert.AreEqual(1, submitResults.Results.Where(e => e.Operation == EntityOperationType.Update).Count());

                // REVIEW: Do we really need the operation data back from the server?
                // ChangeSetEntry returned = submitResults.Results.Single(e => e.OperationName == _assignCityZone.Name);
                // Assert.IsNotNull(returned);
                // Assert.AreEqual(1, returned.OperationData.Count());
            });

            EnqueueTestComplete();
        }
        public void DomainClient_SubmitWithNonexistentDomainMethod()
        {
            TestEntityContainer container = new TestEntityContainer();
            WebDomainClient<CityDomainContext.ICityDomainServiceContract> client = new WebDomainClient<CityDomainContext.ICityDomainServiceContract>(TestURIs.Cities)
            {
                EntityTypes = new Type[] { typeof(City) }
            };
            List<Entity> emptyList = new List<Entity>();
            List<Entity> modifiedEntities = new List<Entity>();

            // invoke domain methods on a few entities
            container.LoadEntities(_cities);

            _cities[0].CustomMethodInvocation = _reject;

            // submit changeset with hand-crafted entities (without calling Invoke)
            modifiedEntities.Add(_cities[0]);
            EntityChangeSet changeset = new EntityChangeSet(emptyList.AsReadOnly(), modifiedEntities.AsReadOnly(), emptyList.AsReadOnly());
            SubmitCompletedResult submitResults = null;
            DomainOperationException expectedException = null;

            EnqueueCallback(delegate
            {
                client.BeginSubmit(
                    changeset,
                    delegate(IAsyncResult asyncResult)
                    {
                        try
                        {
                            submitResults = client.EndSubmit(asyncResult);
                        }
                        catch (DomainOperationException e)
                        {
                            expectedException = e;
                        }
                    },
                    null
                );
            });
            EnqueueConditional(() => expectedException != null);
            EnqueueCallback(delegate
            {
                Assert.IsNull(submitResults);
                Assert.AreEqual("This DomainService does not support operation 'Reject' for entity 'CityWithInfo'.", expectedException.Message);
            });

            EnqueueTestComplete();
        }
 public void Entity_InvokeOnDeleted()
 {
     TestEntityContainer container = new TestEntityContainer();
     container.LoadEntities(_cities);
     container.GetEntitySet<City>().Remove(_cities[2]);
     Assert.AreEqual(EntityState.Deleted, _cities[2].EntityState);
     Assert.IsFalse(_cities[2].CanInvokeAction(_assignCityZone.Name));
     ExceptionHelper.ExpectException<InvalidOperationException>(delegate
     {
         _cities[2].InvokeAction(_assignCityZone.Name, _assignCityZone.Parameters.ToArray());
     }, Resource.Entity_InvokeOnDeletedEntity);
     Assert.AreEqual(0, _cities[2].EntityActions.Count());
     Assert.AreEqual(EntityState.Deleted, _cities[2].EntityState);
 }
        public void PropertyNotification_RaisedOnRejectChanges()
        {
            List<string> propChanged = new List<string>();
            TestEntityContainer container = new TestEntityContainer();
            container.LoadEntities(_cities);

            // invoke domain method and remove the entity
            _cities[0].AssignCityZone("Zone1");
            container.GetEntitySet<City>().Remove(_cities[0]);
            Assert.IsFalse(_cities[0].CanInvokeAction("AssignCityZone"));

            // subscribe to property changed events on entity and call RejectChanges
            _cities[0].PropertyChanged += delegate(object sender, System.ComponentModel.PropertyChangedEventArgs e)
            {
                propChanged.Add(e.PropertyName);
            };
            ((System.ComponentModel.IRevertibleChangeTracking)container).RejectChanges();

            // RejectChanges should raise property changed notification for guard properties
            EnqueueConditional(() => propChanged.Any<string>(p => p.StartsWith("Can")));
            EnqueueCallback(delegate
            {
                Assert.IsTrue(_cities[0].CanInvokeAction("AssignCityZone"));

                // verify RejectChanges does not cause multiple property change notifications
                Assert.IsNotNull(propChanged.Single<string>(p => p == "CanAssignCityZone"));
            });

            EnqueueTestComplete();
        }
        public void Entity_CancelAndEndEdit()
        {
            // BeginEdit -> invoke domain method -> EndEdit. Verify state reverts after End but changeset is not empty.
            TestEntityContainer container = new TestEntityContainer();
            container.LoadEntities(_cities);
            System.ComponentModel.IEditableObject editableCity = _cities[0] as System.ComponentModel.IEditableObject;

            editableCity.BeginEdit();
            _cities[0].InvokeAction(_assignCityZone.Name, _assignCityZone.Parameters.ToArray<object>());
            Assert.AreEqual(EntityState.Modified, _cities[0].EntityState);
            Assert.AreEqual(1, _cities[0].EntityActions.Count());

            editableCity.EndEdit();
            Assert.AreEqual(EntityState.Modified, _cities[0].EntityState);
            Assert.AreEqual(1, _cities[0].EntityActions.Count());

            // begin another session and CancelEdit immediately. Verify that previous invocation is not affected
            editableCity.BeginEdit();
            Assert.IsFalse(_cities[0].CanInvokeAction(_assignCityZone.Name));
            editableCity.CancelEdit();
            Assert.AreEqual(EntityState.Modified, _cities[0].EntityState);
            Assert.AreEqual(1, _cities[0].EntityActions.Count());
        }
        public void EntityContainer_GetChanges_DetachAfterInvoke()
        {
            TestEntityContainer container = new TestEntityContainer();
            container.LoadEntities(_cities);
            EntityChangeSet changeset = container.GetChanges();
            Assert.IsTrue(changeset.IsEmpty);

            // invoke then delete the entity. Verify the ModifiedEntities are updated
            _cities[0].InvokeAction(_assignCityZone.Name, _assignCityZone.Parameters.ToArray<object>());
            Assert.AreEqual(1, _cities[0].EntityActions.Count());
            Assert.AreEqual(1, container.GetChanges().ModifiedEntities.Count());

            container.GetEntitySet<City>().Detach(_cities[0]);
            Assert.AreEqual(0, container.GetChanges().ModifiedEntities.Count());
        }
        public void Entity_InvokeNull_Throws()
        {
            TestEntityContainer container = new TestEntityContainer();
            container.LoadEntities(_cities);
            var invocableCity = _cities[0];
            Assert.IsNotNull(invocableCity);

            ExceptionHelper.ExpectArgumentException(delegate
            {
                invocableCity.InvokeAction(null);
            }, String.Format(Resource.Parameter_NullOrEmpty, "actionName"));

            Assert.AreEqual(EntityState.Unmodified, _cities[0].EntityState);
        }
        public void Entity_Invoke_Unknown_EntityAction()
        {
            TestEntityContainer container = new TestEntityContainer();
            container.LoadEntities(_rootCities);    // root ensures we don't get a derived type which changes message text
            var invocableCity = _rootCities[0];
            Assert.IsNotNull(invocableCity);

            // verify calling Invoke throws InvalidOperationException and the invocation list remains the same
            ExceptionHelper.ExpectException<MissingMethodException>(delegate
            {
                invocableCity.InvokeAction(_reject.Name, _reject.Parameters.ToArray());
            }, string.Format(Resource.ValidationUtilities_MethodNotFound, "Cities.City", _reject.Name, _reject.Parameters.Count(), "'System.String'"));

            Assert.AreEqual(EntityState.Unmodified, _rootCities[0].EntityState);
        }
 public void Entity_InvokeTwiceOnNew()
 {
     TestEntityContainer container = new TestEntityContainer();
     container.LoadEntities(_cities);
     _cities[0].InvokeAction(_assignCityZone.Name, _assignCityZone.Parameters.ToArray());
     Assert.AreEqual<string>(_assignCityZone.Name, _cities[0].EntityActions.Single().Name);
     ExceptionHelper.ExpectException<InvalidOperationException>(delegate
     {
         _cities[0].InvokeAction(_assignCityZone.Name, _assignCityZone.Parameters.ToArray());
     }, "Method can only be invoked once.");
     Assert.AreEqual<string>(_assignCityZone.Name, _cities[0].EntityActions.Single().Name);
     Assert.AreEqual(EntityState.Modified, _cities[0].EntityState);
 }
 public void Entity_InvokeOnUpdated()
 {
     TestEntityContainer container = new TestEntityContainer();
     container.LoadEntities(_cities);
     _cities[1].ZoneID += 1;
     Assert.AreEqual(EntityState.Modified, _cities[1].EntityState);
     Assert.IsTrue(_cities[1].CanInvokeAction(_assignCityZone.Name));
     Assert.IsTrue(_cities[1].EntityState == EntityState.Modified);
     _cities[1].InvokeAction(_assignCityZone.Name, _assignCityZone.Parameters.ToArray());
     Assert.AreEqual(1, _cities[1].EntityActions.Count());
     Assert.AreEqual(_assignCityZone.Name, _cities[1].EntityActions.Single().Name);
     Assert.AreEqual(EntityState.Modified, _cities[1].EntityState);
 }
        public void Entity_DeleteAfterInvoke()
        {
            TestEntityContainer container = new TestEntityContainer();
            container.LoadEntities(_cities);

            // first invoke the action
            City city = _cities.First();
            city.InvokeAction(_assignCityZone.Name, _assignCityZone.Parameters.ToArray());
            Assert.IsFalse(city.CanInvokeAction(_assignCityZone.Name));
            Assert.AreEqual(1, city.EntityActions.Count());

            // delete the entity - expect the actions to be cleared
            container.GetEntitySet<City>().Remove(city);
            Assert.AreEqual(0, city.EntityActions.Count());
            Assert.IsFalse(city.CanInvokeAction(_assignCityZone.Name));
        }
        public void Entity_RejectChanges()
        {
            TestEntityContainer container = new TestEntityContainer();
            container.LoadEntities(_cities);
            _cities[0].InvokeAction(_assignCityZone.Name, _assignCityZone.Parameters.ToArray<object>());
            Assert.AreEqual(1, _cities[0].EntityActions.Count());

            ((System.ComponentModel.IRevertibleChangeTracking)_cities[0]).RejectChanges();
            Assert.AreEqual(0, _cities[0].EntityActions.Count());
            Assert.AreEqual(EntityState.Unmodified, _cities[0].EntityState);

            var invocableCity = _cities[0];
            Assert.AreEqual(0, invocableCity.EntityActions.Count());
        }
        public void Entity_EntityAction_InvokeOnLoaded()
        {
            // verify initial state: empty invocations and one can invoke any methods
            TestEntityContainer container = new TestEntityContainer();
            container.LoadEntities(_cities);
            var invocableCity = _cities[1];
            Assert.IsNotNull(invocableCity);
            Assert.IsTrue(invocableCity.CanInvokeAction(_assignCityZone.Name));

            Assert.AreEqual(0, invocableCity.EntityActions.Count());

            // verify invoke on a new entity succeeds and subsequent CanInvoke for a different entity action returns false
            invocableCity.InvokeAction(_assignCityZone.Name, _assignCityZone.Parameters.ToArray());
            Assert.IsFalse(invocableCity.CanInvokeAction(_assignCityZone.Name)); // different entity action name
            Assert.AreSame(_assignCityZone.Name, _cities[1].EntityActions.Single().Name);

            // verify you get back the same entity action on GetInvocations
            Assert.AreEqual<string>(_assignCityZone.Name, invocableCity.EntityActions.Single().Name);
        }
        public void EntityContainer_GetChanges()
        {
            TestEntityContainer container = new TestEntityContainer();
            container.LoadEntities(_cities);
            EntityChangeSet changeset = container.GetChanges();
            Assert.IsNotNull(changeset);
            Assert.IsTrue(changeset.IsEmpty);

            // invoke domain method on 2 cities and verify invocation is in changeset
            // TODO: need 2 separate legal domain methods
            _cities[0].InvokeAction(_assignCityZone.Name, _assignCityZone.Parameters.ToArray<object>());
            _cities[2].InvokeAction(_assignCityZone.Name, _assignCityZone.Parameters.ToArray<object>());
            changeset = container.GetChanges();
            Assert.IsTrue(changeset.AddedEntities.Count == 0);
            Assert.IsTrue(changeset.ModifiedEntities.Count == 2);
            Assert.IsTrue(changeset.RemovedEntities.Count == 0);

            Assert.AreEqual<string>(_assignCityZone.Name, changeset.ModifiedEntities[0].EntityActions.Single().Name);
            Assert.AreEqual<string>(_assignCityZone.Name, changeset.ModifiedEntities[1].EntityActions.Single().Name);

            // revert one of the domain method invocations. verify invocation in changeset is updated
            ((System.ComponentModel.IRevertibleChangeTracking)_cities[0]).RejectChanges();
            changeset = container.GetChanges();
            City returned = changeset.ModifiedEntities.Single(p => p == _cities[2]) as City;
            Assert.IsNotNull(returned);
            Assert.AreEqual<string>(_assignCityZone.Name, returned.EntityActions.Single().Name);
            Assert.AreEqual<int>(_assignCityZone.Parameters.Count(), returned.EntityActions.Single().Parameters.Count());
        }
        public void Inherit_Run_Entity_ReadOnly()
        {
            TestEntityContainer container = new TestEntityContainer();
            container.LoadEntities(_citiesWithInfo);

            Assert.IsFalse(_citiesWithInfo[0].IsReadOnly);
            _citiesWithInfo[0].SetCityInfo("new stuff");
            Assert.IsTrue(_citiesWithInfo[0].IsReadOnly);

            ((System.ComponentModel.IRevertibleChangeTracking)_cities[0]).RejectChanges();

            Assert.IsFalse(_citiesWithInfo[1].IsReadOnly);
        }
        public void Entity_CancelEdit()
        {
            // verify that DomainMethod invocations participate in IEditableObject sessions properly
            TestEntityContainer container = new TestEntityContainer();
            container.LoadEntities(_cities);
            System.ComponentModel.IEditableObject editableCity = _cities[0] as System.ComponentModel.IEditableObject;
            Assert.IsNotNull(editableCity);

            editableCity.BeginEdit();
            int prevZoneID = _cities[0].ZoneID;
            _cities[0].ZoneID = 777;
            _cities[0].InvokeAction(_assignCityZone.Name, _assignCityZone.Parameters.ToArray<object>());
            Assert.AreEqual(1, _cities[0].EntityActions.Count());

            // cancel editing. Domain method invocation and property updates are reverted
            editableCity.CancelEdit();
            Assert.AreEqual(prevZoneID, _cities[0].ZoneID);
            Assert.AreEqual(0, _cities[0].EntityActions.Count());
            Assert.AreEqual(EntityState.Unmodified, _cities[0].EntityState);
            Assert.IsTrue(container.GetChanges().IsEmpty);

            // now start an edit session with a modified entity
            // and verify same results
            _cities[0].ZoneID = 777;
            Assert.AreEqual(EntityState.Modified, _cities[0].EntityState);
            editableCity.BeginEdit();
            _cities[0].ZoneID = 888;
            _cities[0].InvokeAction(_assignCityZone.Name, _assignCityZone.Parameters.ToArray<object>());
            editableCity.CancelEdit();
            Assert.AreEqual(777, _cities[0].ZoneID);
            Assert.AreEqual(0, _cities[0].EntityActions.Count());
            Assert.AreEqual(EntityState.Modified, _cities[0].EntityState);

            // now test an edit session where only a DM was invoked (no property edits)
            ((System.ComponentModel.IRevertibleChangeTracking)_cities[0]).RejectChanges();
            Assert.AreEqual(EntityState.Unmodified, _cities[0].EntityState);
            editableCity.BeginEdit();
            _cities[0].InvokeAction(_assignCityZone.Name, _assignCityZone.Parameters.ToArray<object>());
            Assert.AreEqual(EntityState.Modified, _cities[0].EntityState);
            editableCity.CancelEdit();
            Assert.AreEqual(EntityState.Unmodified, _cities[0].EntityState);
            Assert.IsTrue(container.GetChanges().IsEmpty);
        }
        public void Entity_InvokeOnAdded()
        {
            TestEntityContainer container = new TestEntityContainer();
            City city = new City { Name = "Redmond", CountyName = "King", StateName = "WA" };
            container.GetEntitySet<City>().Add(city);
            Assert.AreEqual(EntityState.New, city.EntityState);
            Assert.AreEqual(0, city.EntityActions.Count());
            Assert.IsTrue(city.CanInvokeAction(_assignCityZone.Name));

            city.InvokeAction(_assignCityZone.Name, _assignCityZone.Parameters.ToArray());
            Assert.AreEqual(1, city.EntityActions.Count());
            Assert.AreEqual(EntityState.New, city.EntityState);
            Assert.AreEqual<string>(_assignCityZone.Name, city.EntityActions.Single().Name);
            Assert.AreEqual<int>(_assignCityZone.Parameters.Count(), city.EntityActions.Single().Parameters.Count());
            Assert.IsFalse(city.CanInvokeAction(_assignCityZone.Name));
        }
        public void Entity_Invoke_Validates_Entity_Validation()
        {
            TestEntityContainer container = new TestEntityContainer();
            container.LoadEntities(_rootCities);    // root ensures we don't get a derived type which changes message text
            var invocableCity = _rootCities[0];
            Assert.IsNotNull(invocableCity);

            invocableCity.ZoneID += 1;
            invocableCity.StateName = "WA";
            invocableCity.MakeEntityValidationFail = true;

            ExceptionHelper.ExpectValidationException(delegate
            {
                invocableCity.AssignCityZone("West");
            }, "MakeEntityValidationFail is true", typeof(CustomValidationAttribute), invocableCity);
        }
        public void DomainClient_SubmitWithInvalidInvocation()
        {
            TestEntityContainer container = new TestEntityContainer();
            WebDomainClient<CityDomainContext.ICityDomainServiceContract> client = new WebDomainClient<CityDomainContext.ICityDomainServiceContract>(TestURIs.Cities)
            {
                EntityTypes = new Type[] { typeof(City) }
            };
            List<Entity> emptyList = new List<Entity>();
            List<Entity> modifiedEntities = new List<Entity>();

            // verify exception is thrown when trying to invoke invalid action
            ExceptionHelper.ExpectArgumentException(delegate
            {
                _cities[0].InvokeAction("");
            }, string.Format(CultureInfo.CurrentCulture, Resource.Parameter_NullOrEmpty,"actionName"));
        }
        public void Entity_Invoke_Validates_Required_Properties()
        {
            TestEntityContainer container = new TestEntityContainer();
            var invocableCity = new City();
            container.GetEntitySet<City>().Add(invocableCity);

            RequiredAttribute expectedAttribute = new RequiredAttribute();
            string expectedMember = "CityName";
            string expectedError = expectedAttribute.FormatErrorMessage(expectedMember);

            ExceptionHelper.ExpectValidationException(delegate
            {
                invocableCity.AssignCityZone("West");
            }, expectedError, expectedAttribute.GetType(), null);
        }
        public void PropertyNotification_RaisedOnDelete()
        {
            List<string> propChanged = new List<string>();
            TestEntityContainer container = new TestEntityContainer();
            container.LoadEntities(_cities);
            Assert.IsTrue(_cities[0].CanInvokeAction("AssignCityZone"));

            // subscribe to property changed events on entity and Remove
            _cities[0].PropertyChanged += delegate(object sender, System.ComponentModel.PropertyChangedEventArgs e)
            {
                propChanged.Add(e.PropertyName);
            };
            container.GetEntitySet<City>().Remove(_cities[0]);

            // Deleting entity should raise property changed notification for guard properties
            EnqueueConditional(() => propChanged.Any<string>(p => p.StartsWith("Can")));
            EnqueueCallback(delegate
            {
                Assert.IsFalse(_cities[0].CanInvokeAction("AssignCityZone"));
            });

            EnqueueTestComplete();
        }
        public void Entity_Invoke_Validates_Property_Validation()
        {
            TestEntityContainer container = new TestEntityContainer();
            var invocableCity = new City("This is an invalid state name");
            container.GetEntitySet<City>().Add(invocableCity);

            invocableCity.Name = "Redmond";

            StringLengthAttribute expectedAttribute = new StringLengthAttribute(2);
            string expectedMember = "StateName";
            string expectedError = expectedAttribute.FormatErrorMessage(expectedMember);

            ExceptionHelper.ExpectValidationException(delegate
            {
                invocableCity.AssignCityZone("West");
            }, expectedError, expectedAttribute.GetType(), invocableCity.StateName);
        }
        public void Inherit_Run_Entity_Invoke_Illegal_EntityAction()
        {
            TestEntityContainer container = new TestEntityContainer();
            container.LoadEntities(_rootCities);
            var invocableCity = _rootCities[0];
            Assert.IsNotNull(invocableCity);

            // verify calling Invoke throws InvalidOperationException and the invocation list remains the same
            ExceptionHelper.ExpectException<MissingMethodException>(delegate
            {
                invocableCity.InvokeAction(_setCityInfo.Name, _setCityInfo.Parameters.ToArray());
            }, string.Format(Resource.ValidationUtilities_MethodNotFound, "Cities.City", _setCityInfo.Name, _setCityInfo.Parameters.Count(), "'System.String'"));

            Assert.AreEqual(EntityState.Unmodified, _rootCities[0].EntityState);
        }