views:

469

answers:

3

Hi, I'm trying to write a WCF method that will receive a detached EntityObject from the client and will be able to tell which properties and which relationships were changed for this entity comparing it with what's already in the context. Of course that if this entity is a new entity or one of its relationships were added/deleted/modified it should also recognize that and act accordingly.

I'm already able to recognize if the entity's relationship is a new one but can't seem to be able to add it correctly. -With every approach I try I get a different exception.

Here is the method I use to update the detached object:

public static void AttachUpdated(this ObjectContext context, EntityObject objectDetached)
{
    if (objectDetached.EntityState == EntityState.Detached)
    {
        object currentEntityInDb = null;

        if (context.TryGetObjectByKey(objectDetached.EntityKey, out currentEntityInDb))
        {
            context.ApplyPropertyChanges(objectDetached.EntityKey.EntitySetName, objectDetached);
            //Apply property changes to all referenced entities in context 
            context.ApplyReferencePropertyChanges((IEntityWithRelationships)objectDetached,
                                                  (IEntityWithRelationships)currentEntityInDb); //Custom extensor method 
        }
        else
        {
            //The entity should be added
            //?????
        }
    }
}

And this is a method I use to update the entity's relationships:

public static void ApplyReferencePropertyChanges(this ObjectContext context,
                                                         IEntityWithRelationships newEntity,
                                                         IEntityWithRelationships oldEntity)
{
    foreach (var oldRelatedEnd in oldEntity.RelationshipManager.GetAllRelatedEnds())
    {
        var oldRef = oldRelatedEnd as EntityReference;

        if (oldRef != null)
        {
            // this related end is a reference not a collection 
            var newRef = newEntity.RelationshipManager.GetRelatedEnd(oldRef.RelationshipName, oldRef.TargetRoleName) as EntityReference;
            if (newRef.EntityKey != null)
            {
                oldRef.EntityKey = newRef.EntityKey;
            }
            else
            {   
                //When oldRed is a 1:Many relationship
                //newRef is an EntityReference<TEntity> object
                EntityObject entity = newRef.GetType().GetProperty("Value").GetValue(newRef, null) as EntityObject;
                oldRef.EntityKey = entity.EntityKey;
            }
        }
        else
        {
            IRelatedEnd newRelatedEnd = newEntity.RelationshipManager.GetRelatedEnd(oldRelatedEnd.RelationshipName, oldRelatedEnd.TargetRoleName);
            foreach (IEntityWithRelationships e in newRelatedEnd)
            {
                if (!oldRelatedEnd.Contains((e as IEntityWithKey).EntityKey))
                {
                    //this is a new relation and it needs to be added.
                    //???????
                }
                else
                {
                    //Find out if relation was modified - and update it if needed
                    //????????
                }
            }
            IEnumerable entities = oldRelatedEnd as IEnumerable;

        }
    }
}

How should it be implemented?

Please help :(

A: 

Where is your ObjectContext coming from? (I am assuming that this is your Entity Framework database reference)

There may be two problems here:

Firstly, I do not think that ObjectContext is serializable, so if you are sending it to the client and then sending it back, you will get an error.

Secondly, If you are keeping ObjectConext on the server, the server objects are by default per call, not per session, therefore you will be trying to associate your Entity with a new ObjectContext.

In our projects we map Entity framework Objects to data transfer objects in order to send then over WCF. What you are trying to do may be easier (possible?) in the next version of Entity Framework.

Shiraz Bhaiji
A: 

I'm not sure what you want to achieve - if you want to save the changes in the server side you can use ADO .Net Data Services. Is that the case?

nirpi
A: 

See Perseus:

Perseus is a small project designed to explore ways for exchanging graphs of Entity Framework entities over WCF web services. The key piece of the project is EntityBag which stores a graph of entities along with change tracking information. Here's hoping no one will use this to store & transport something as nasty as Medusa's head. ;-)

John Saunders