locked
EF + WCF + Update failure RRS feed

  • Question

  • Hi guys,

    I have a application that I have a server and client app. When from my client I request a entity from server I observed its EntityState and I checked that exactly after search I got EntityState=Unchanged. When I sent this entity to client over WCF the client received this same entity with EntityState=Detached. Then I did all modifications that I want and sent back to server over WCF and on server I received this entity with EntityState=Detached. Fine, then start the problems.

    1) If I try Attach again  this entity in my context I receive a error saying that this entity already exist in my context.
    2) Then I made search on the internet and I found someone talk about N-tier and EF and He write the follow code:

                EntityKey key = ((IEntityWithKey)current).EntityKey;
                object original = null;

                if (key != null)
                {
                    original = GetObjectByKey(key);
                    ApplyPropertyChanges(entitySetName, current);
                }
                int changes = SaveChanges();

    Now I didn't receive any error but this code didn't save my entity. If I write the variable changes I received zero changes.


    3) Then I try to set all properties of my entity to modified. Like this code:

       public void SetAllModified(IEntityWithKey entity)
            {
                var stateEntry = ObjectStateManager.GetObjectStateEntry(entity.EntityKey);
                var propertyNameList = stateEntry.CurrentValues.DataRecordInfo.FieldMetadata.Select(pn => pn.FieldType.Name);
                foreach (var propName in propertyNameList)
                    stateEntry.SetModifiedProperty(propName);
            }


    Again, when I call SaveChanges method nothing happen. My object still dont have changes.

    Guys, What can i do to solve this problem?

    Friday, October 30, 2009 11:46 AM

Answers

  • Hi Eliezer,

     

     

    In EF 3.5, if you want to update with child entity, it is not easy to achieve. You may have to use hard code for it.

    You can refer to this thread about the sample,

    http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/0a72c7bf-7899-4ddd-ba0d-fef3586ecfa9

     

    The point is, do not set the navigate property before passing to the update method.

     

    The good news is that is has been fixed in EF4. Here is a reply from product team about updating with related entity in N-tier project,

     

    This is a big topic.  The real fixes for this topic come in EF4, and you can read more about them on the EFDesign blog (http://blogs.msdn.com/efdesign/archive/2009/03/24/self-tracking-entities-in-the-entity-framework.aspx, http://blogs.msdn.com/efdesign/archive/2008/11/20/n-tier-improvements-for-entity-framework.aspx).  You can also take a look at my short series of MSDN Magazine articles (http://msdn.microsoft.com/en-us/magazine/dd876635.aspx with another article coming in a future issue).”

     

     

    Best Regards

    Yichun Feng


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    • Marked as answer by Eliezer Reis Friday, November 6, 2009 12:10 AM
    Tuesday, November 3, 2009 4:35 AM

All replies

  • up!!
    Friday, October 30, 2009 12:24 PM
  • What you did in (2) should have worked - see the following link and notice it's the same:
    http://msdn.microsoft.com/en-us/library/bb896248.aspx

    Can you explain what you've changed on the client side? a scalar property ? a navigation property? have you changed the "current" object or one of its related objects?

    Please mark posts as answers/helpful if it answers your question
    Friday, October 30, 2009 1:21 PM
  • Well, the entity that I'd like to change there's this properties.

    ReferenceStory
       - StoryId (PK and FK)
       - Link
       - Story (relashionship)
             - ID (PK)
             - Title
             - Name
             - Priority (relashionhip)
                  -ID (PK)
                  -Name


    I'm try to change Title (of story) and Priority (this is another entity) of my ReferenceStory .

    All the scenario is:
    - User use WCF to request All ReferenceStory.
    - WCF Service receive request and do search in database. Like this:

    var query = from ref in ReferenceStories select ref;
    query.ToList<RefenceStory>();

    - Then I get  this list and sent back to client and fill DataGrid.
    - User double click on a row of my grid and I show a Form with all properties of the selected item of grid. I get selected item based on DataSource setted by binding. At this moment I check that this EntityState = Detached;
    - User do your changes and press save. I get changes and modified the selectedItem and sent this entity back  to server using WCF.
    -  Server receive this entity correctly with EntityState still equals Detached. Then I passed this entity for my GenericDAO. I tried a lot of thing, but this is a least version  that I have of my GenericDAO. Observe that I'm inheriting from Entities that is my context.
    - After that, nothing changes.

    It's all that I'm doing. I dont know what can I do to save my entities. It's to stranger!


     public class GenericDAO<TEntity> : Entitties, IGenericDAO<TEntity>
        {
            Type t = null;
            string entitySetName;

            public GenericDAO()
            {
                t = typeof(TEntity);
                entitySetName = GetEntitySetName(t.Name);
            }

            private string GetEntitySetName(string entityTypeName)
            {

                var container = MetadataWorkspace.GetEntityContainer(DefaultContainerName, DataSpace.CSpace);
                string entitySetName = (from meta in container.BaseEntitySets
                                        where meta.ElementType.Name == entityTypeName
                                        select meta.Name).FirstOrDefault();
                return entitySetName;
            }

           (.....)

            public void update(TEntity entity)
            {
                AttachUpdated(entity);
                SaveChanges();
            }

       
            public void AttachUpdated(TEntity current)
            {
                object original = null;
                EntityKey key = CreateEntityKey(entitySetName, current);

                if (TryGetObjectByKey(key, out original))
                {
                    ApplyPropertyChanges(entitySetName, current);

                    var newEntity = current as IEntityWithRelationships;
                    var oldEntity = original as IEntityWithRelationships;

                    if (newEntity != null && oldEntity != null)
                    {
                        ApplyReferencePropertyChanges(newEntity, oldEntity);
                    }
                }
                else
                {
                    throw new ObjectNotFoundException();
                }
            }

            public void ApplyReferencePropertyChanges(IEntityWithRelationships newEntity, IEntityWithRelationships oldEntity)
            {
                foreach (var relatedEnd in oldEntity.RelationshipManager.GetAllRelatedEnds())
                {
                    var oldReference = relatedEnd as EntityReference;

                    if (oldReference != null)
                    {
                        var newReference = newEntity.RelationshipManager.GetRelatedEnd(oldReference.RelationshipName,
                            oldReference.TargetRoleName) as EntityReference;

                        if (newReference != null)
                        {
                            oldReference.EntityKey = newReference.EntityKey;
                        }
                    }
                }
            }
     
         (.....)


    }


    Friday, October 30, 2009 2:29 PM
  • Now it's obvious where the problem is - you update one of the referenced entities, not the entity itself. After you attach the entity, the entire entity graph should be attached - by the way, note that if you had added a new entity to the graph, you would have gotten an exception.

    After you attach your entities, you need to use the ApplyPropertyChanges on each and every entity - not only at the root entity.

    You can either do it manually (for each entity in the graph) or you can use the ObjectStateManager property from the ObjectContext to get a list of all entities in the context and iterate them and for each one call the AttachUpdated method you've created
    Please mark posts as answers/helpful if it answers your question
    Saturday, October 31, 2009 10:52 AM
  • I'm complete frustated with EntityFramework. A lot of things that i'm try to do is incomprehensible.
    I have a lot of disgusted for this framework If you observe is complete incomprehensible for me to do a lot of this extra code for upgrade one entity. Is logical that if i want work with ORM is necessary that changes and actions between objects should OOP. Then if one entity that has one-to-one relashionship with another entity this entity is part of root entity. Then any operation in Employee (for example) the framework need understand that Adress have to be upgrade in cascade. 

    Come on, Why is necessary my entity inheritance from EntityObject if this don't give benefic that they say that this entity do. If i have to operations like SQL is better work just with POCO as in NHibernate(of course that i cant wait to .net 4.0) Take a look for another stupid problem. Employee may have a lot of phones. Imagine that I change one phone from one Employee.I can't just change the list of phone that i have in Employee. I have to delete the employee reference in phone entity and then add another phone in employye phones list and still, go to phones and add employee for you list. 

     You see? I dont know if i'm readable but in resume a just wanna tell you that EF is too trash. For me EF is too imature and I hope that version 4.0 (EF2.0?) comes better. 

    And I was making search i saw one post from developer of microsoft and he told to us that i he know all of this problem and they are working on it. For me its sound like.....go try another thing better that our framework is still imature.

     Sorry, but I know that using It in a real project.
    Saturday, October 31, 2009 11:44 PM
  • Hi Eliezer,

     

     

    In EF 3.5, if you want to update with child entity, it is not easy to achieve. You may have to use hard code for it.

    You can refer to this thread about the sample,

    http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/0a72c7bf-7899-4ddd-ba0d-fef3586ecfa9

     

    The point is, do not set the navigate property before passing to the update method.

     

    The good news is that is has been fixed in EF4. Here is a reply from product team about updating with related entity in N-tier project,

     

    This is a big topic.  The real fixes for this topic come in EF4, and you can read more about them on the EFDesign blog (http://blogs.msdn.com/efdesign/archive/2009/03/24/self-tracking-entities-in-the-entity-framework.aspx, http://blogs.msdn.com/efdesign/archive/2008/11/20/n-tier-improvements-for-entity-framework.aspx).  You can also take a look at my short series of MSDN Magazine articles (http://msdn.microsoft.com/en-us/magazine/dd876635.aspx with another article coming in a future issue).”

     

     

    Best Regards

    Yichun Feng


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    • Marked as answer by Eliezer Reis Friday, November 6, 2009 12:10 AM
    Tuesday, November 3, 2009 4:35 AM
  • Yes, We just have to wait for .net 4.0. Meanwhile we using NHibernate :)

    The problem is, if is necessary sacrifice my POCO for EntityObject this entity have to give me a lot of benefic. Worse, if I chose to use ORM so I hope work with entities clearly, intuitively using OOP and more, EF has not good integration in an architecture layered then it should also be thought. We do sofware client/server often than we hope better integration with WCF, but this doesnt happen.

    Thanks a lot, this was my outburst!
    Tuesday, November 3, 2009 12:21 PM