ontehfritz – Application Development and Stuff

November 25, 2008

.Net Entity Framework Deleting Objects in N-Tier Environment

Filed under: .Net Entity Framework 3.5 SP1 — ontehfritz @ 12:46 pm

Well, here I am again, This has turned into a mini series. Please see Adding Objects and Updating Objects for the other episodes of fun!

Deleting objects in an N-Tier environment has been a pleasure and worked as expected. Here we go!

WCF Methods:

/*Private method so I do not have to duplicate these lines everytime*/
  private void Delete(EntityObject o)
    {
        using(CorporateEntities ce = new CorporateEntities())
        {
            ce.Attach(o);
            ce.DeleteObject(o);
            ce.SaveChanges();
        }
    }

/*The exposed method to delete a Store from the database*/

    public void RemoveStore(Stores removeStore)
    {
        this.Delete(removeStore);
    }

Nice eh ..? finally something simple and meaningful.

Now for the client code:

 client.RemoveStore(client.GetStoreByID(666)); /*WCF Method to retrieve the store I want to delete*/

That is it!!! Not much left to say on deleting. We now have completed this mini series on Adding, Updating and Deleting Objects in N-Tier environment using the entity framework. I will post updates on the posts made when I find better ways to do these operations, but for now this is what works.

Hopes this helps people and avoids the struggles I had. Please post links to better solutions and/or in the comments.

Stay Cool ;)

Note and Disclaimer: This is test code and may contain bugs and/or improper error handling, it is for academic purposes only, for sharing knowledge, and collaboratively coming up with better solutions. Please always practice proper security, error handling, and coding best practices in production. I am not liable for any code used here; use @ your own risk. Have fun and share the experience and knowledge. Remember, no question is a stupid question, and failure gives us insight.

November 21, 2008

.Net Entity Framework Updating Objects in N-Tier Environment

Filed under: .Net Entity Framework 3.5 SP1 — Tags: — ontehfritz @ 11:37 am

Oh, Boy. OK, Phew. This was quite the deal to get Objects with navigation properties to update. The issue with updates is this, when using the method:

yourcontext.ApplyPropertyChanges(key.EntitySetName, o);

It only works on scalar properties in your entity object. Not the navigation properties or the reference objects (Foreign Key Relationships). I composed from the very few resources on the entity framework this method in my WCF Service:
Credits to this blog entry for guiding me in the right direction. Check it out.

private void Update(System.Data.Objects.DataClasses.EntityObject o)
    {
        EntityKey key;
        Object originalItem;

        using (CorporateEntities ce = new CorporateEntities())
        {
            key = ce.CreateEntityKey(o.EntityKey.EntitySetName, o);

            if (ce.TryGetObjectByKey(key, out originalItem))
            {
                ce.ApplyPropertyChanges(
                        key.EntitySetName, o);

                foreach (var entityrelationship in ((IEntityWithRelationships)originalItem).RelationshipManager.GetAllRelatedEnds())
                {
                    var oldRef = entityrelationship as EntityReference;

                    if (oldRef != null)
                    {
                        var newRef = ((IEntityWithRelationships)o).RelationshipManager.GetRelatedEnd(oldRef.RelationshipName, oldRef.TargetRoleName) as EntityReference;
                        oldRef.EntityKey = newRef.EntityKey;
                    }
                }
            }

            ce.SaveChanges();
        }
    }

This method takes the new object and updates the old objects EntityKeys. Why do we have to cast the Entity Object to IEntityWithRelationShips? According to documentation on MSDN it implements IEntityWithRelationShips. Check it out Shouldn’t it be available already. Anyway, Once we do this we can retrieve each navigation property or references; then change the old to the new. However, there is a catch here. If You do not change the entity key on the YourObjectReference it will not update it with new reference object. For example on the client:

Stores updateStore = client.GetStoreByID(666);
/*This has no effect as the updateStore.ConceptsReference will not be updated by the line below*/
updateStore.Concepts = client.GetConcept(3);

“Concepts” is the navigation property and seems logical to assign new object to this, but unfortunately it will have no effect on updating because the updateStore.ConceptReference still points to the original entity. So we need to change the reference. In my WCF Service I have created the following method to do this for me. The not so cool part is that I pass in the navigation properties or objects as a separate parameter on the method. This is to abstract the Presentation Layer from having Entity Framework (EF) specific code in it. Remember ideally the presentation layer should only worry about business objects, not specific Data Access Layer (DAL) nuances.

public void UpDateStore(Stores updatedStore, Concepts concept, StoreStatus status, Distributors distributors, POSSystems pos)
    {
        EntityReference c = new EntityReference();
        c.EntityKey = concept.EntityKey;
        updatedStore.ConceptsReference = c;

        EntityReference s = new EntityReference();
        s.EntityKey = status.EntityKey;
        updatedStore.StoreStatusReference = s;

        EntityReference d = new EntityReference();
        d.EntityKey = distributors.EntityKey;
        updatedStore.DistributorsReference = d;

        EntityReference p = new EntityReference();
        p.EntityKey = pos.EntityKey;
        updatedStore.POSSystemsReference = p;

        updatedStore.ModifiedDate = DateTime.Now;
        this.Update(updatedStore);
    }

So now when I call my private update method in the WCF Service it will indeed update!

Client code:

Stores updateStore = client.GetStoreByID(666);
client.UpDateStore(updateStore, client.GetConcept(2), client.GetStat(2), client.GetDistributor(2), client.GetPOSSystem(2));

Hope this helps anyone else struggling with this situation. Better yet if someone can post a more elegant solution that would be great. There is very little information on real world examples of using Entity Framework, especially in N-Tier environment.

Note and Disclaimer: This is test code and may contain bugs and/or improper error handling, it is for academic purposes only, for sharing knowledge, and collaboratively coming up with better solutions. Please always practice proper security, error handling, and coding best practices in production. I am not liable for any code used here; use @ your own risk. Have fun and share the experience and knowledge. Remember, no question is a stupid question, and failure gives us insight.

November 19, 2008

.Net Entity Framework Adding New Objects in N-Tier Environment

Filed under: .Net Entity Framework 3.5 SP1 — Tags: — ontehfritz @ 9:31 pm

Through out my my career as a Application Developer; this thought runs through my head when using new technology such as the Entity Framework, “Is there something wrong with me, how come new technology makes me feel like I have a lack of brain cells, or my neural networks didn’t develop properly when younger, or am I simply mad?”  Making great enterprise applications is my goal. When something like the Entity Framework comes out I am immediatly drawn to the potentials of such a framework.

My problem; I have N-Tier environment, with WCF service that uses the Entity Framework. The service contains a method:

WCF Service Method ———-

public void AddStore(Stores newStore)
{
using (CorporateEntities ce = new CorporateEntities())
{
newStore.CreatedDate = DateTime.Now;

ce.AddObject("Stores", newStore);
ce.SaveChanges();
}
}

END of Method ——-
Stores is the entity from my data model.  Awesome. Simple cool. However it isn’t this simple. To get this to work on client side I had to do this. You would think you could simply pass in a Store object and add it. LOL, nooooooo. That would be crazy.

 

Client Code  That works ———

Stores newStore = new Stores();
/* Why cant assign it like this
newStore.Concepts = client.GetConcept(0);
because we can't sorry doesn't work
*/
Concepts concept = client.GetConcept(0);
Distributors dist = client.GetDistributor(1);
StoreStatus status = client.GetStat(1);

POSSystems pos = client.GetPOSSystem(1);
newStore.LongName = "The besttes store in the whole world";
newStore.ShortName = "Awesomeness";
newStore.ID = 666;
newStore.IsActive = false;
newStore.IsGroups = false;
newStore.IsKidsBirthdays = false;
newStore.IsLab = false;
newStore.IsReservations = false;
newStore.IsShowWeb = false;
newStore.IsTakeOut = false;
newStore.IsWheelChairAccessible = false;

/* This is what we do to get it to work .... not pretty*/
EntityReferenceOfStoreStatusexoxzxyP statusReference = new EntityReferenceOfStoreStatusexoxzxyP();
statusReference.EntityKey = status.EntityKey;
newStore.StoreStatusReference = statusReference;

EntityReferenceOfConceptsexoxzxyP conceptReference = new EntityReferenceOfConceptsexoxzxyP();
conceptReference.EntityKey = concept.EntityKey;
newStore.ConceptsReference = conceptReference;

EntityReferenceOfPOSSystemsexoxzxyP posReference = new EntityReferenceOfPOSSystemsexoxzxyP();
posReference.EntityKey = pos.EntityKey;
newStore.POSSystemsReference = posReference;

EntityReferenceOfDistributorsexoxzxyP distroReference = new EntityReferenceOfDistributorsexoxzxyP();
distroReference.EntityKey = dist.EntityKey;
newStore.DistributorsReference = distroReference;
client.AddStore(newStore);

End of that works Client Code ———————————–
Wow, Weird eh?!?!? It would be great just to do.

Stores newStore = new Stores();
newStore.Concepts = client.GetConcept(1);

then simply:

client.AddStore(newStore);

You can try attaching the referenced table objects, etc, but no matter what you do you may see exceptions like:

“An object with the same key already exists in the ObjectStateManager. The existing object is in the Unchanged state. An object can only be added to the ObjectStateManager again if it is in the added state.”…

Update Nov 21, 2008
Ok, so an update. I am leaving the post as is. Just to see the steps I have gone through and some wierd ways to make inserting objects in N-Tier environment work. Here is some updated code on solution that is better, but still far from ideal!

–Updated WCF Method

 public void AddStore(Stores newStore, Concepts concept, StoreStatus status, Distributors distributors, POSSystems pos)
    {
        using (CorporateEntities ce = new CorporateEntities())
        {

            EntityReference<Concepts> c = new EntityReference<Concepts>();
            c.EntityKey = concept.EntityKey;
            newStore.ConceptsReference = c;

            EntityReference<StoreStatus> s = new EntityReference<StoreStatus>();
            s.EntityKey = status.EntityKey;
            newStore.StoreStatusReference = s;

            EntityReference<Distributors> d = new EntityReference<Distributors>();
            d.EntityKey = distributors.EntityKey;
            newStore.DistributorsReference = d;

            EntityReference<POSSystems> p = new EntityReference<POSSystems>();
            p.EntityKey = pos.EntityKey;
            newStore.POSSystemsReference = p;

            newStore.CreatedDate = DateTime.Now;

            ce.AddObject("Stores", newStore);
            ce.SaveChanges();
        }
    }

and then a more clean client code with the weirdness of having to pass in the Navigation or Relationship objects for the change.

/*client is the WCF instance*/
client.AddStore(newStore, client.GetConcept(0), client.GetStat(1), client.GetDistributor(1), client.GetPOSSystem(1));

A little better, a little cleaner, a little weird still. All the get methods used in the method parameters are WCF methods(Just to clarify).

 

Some nice web sources explaining that we will have to deal with this elegant retarded framework. Check it out. We will be dealing with these nuances for awhile. Typical!

End of Nov, 21, 2008 update

This is what worked for me. Kind of like WTF, “This is what I have to do to add a new object that has foreign key relationship with other tables….?” Yup, No access to the ID fields of the related objects just the object itself. All I want to do is only deal with objects on the presentation layer. I don’t want the presentation layer to know that I am using the entity framework, but unfortunately I have not seen any better solutions.

Thats it for now, peeps. ;)

Note and Disclaimer: This is test code and may contain bugs and/or improper error handling, it is for academic purposes only, for sharing knowledge, and collaboratively coming up with better solutions. Please always practice proper security, error handling, and coding best practices in production. I am not liable for any code used here; use @ your own risk. Have fun and share the experience and knowledge. Remember, no question is a stupid question, and failure gives us insight.

Blog at WordPress.com.