Generic Fetch Entity Method

Posts   
 
    
Posts: 5
Joined: 01-Mar-2009
# Posted on: 01-Mar-2009 08:57:44   

I'm trying to create a generic method to fetch an entity in my repository layer. I came up with the following that fetches the entity with the correct data loaded, but when you try to set or read a property on the fetched entity, it throws the "entity is out of sync" error. Since I am using the ForcedCurrentValueWrite method that I'm not supposed to use, I wonder what the correct way to do this is, if it's even possible. confused


public ET GetEntity<ET, PKT>(PKT primaryKey) where ET : IEntity2, new()
        {
            using (DataAccessAdapter adapter = new DataAccessAdapter())
            {
                ET entity = new ET();
                IList<IEntityField2> pks = entity.PrimaryKeyFields;
                pks[0].ForcedCurrentValueWrite(primaryKey);
                adapter.FetchEntity(entity);                
                return entity;
            }
        }

Any thoughts?

thanks, jim

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 01-Mar-2009 17:52:00   

Does this happen every time? For example, is the entity successfully fetched? Please post the code when you call this method and then access the properties (are you doing things between the fetch and when you read the property?).

David Elizondo | LLBLGen Support Team
Posts: 5
Joined: 01-Mar-2009
# Posted on: 02-Mar-2009 07:52:16   

Yes, the entity appears to be fetched successfully based on it's contents. I simply return the from my generic get method, then do:


var locItem = myrepository.Get<LocationItemEntity, Guid>(keyVal);  // or real close, I deleted the code already
if (locItem != null)
            {
                if (locItem.LocationItemStatusId != Globals.Constants.LocationItemStatus.PAUSED)
                       ...

It throws the entity out of sync exception when trying to access the locItem.LocationItemStatusId property.

thanks

Walaa avatar
Walaa
Support Team
Posts: 14993
Joined: 21-Aug-2005
# Posted on: 02-Mar-2009 09:45:49   

Try this:

        public ET GetEntity<ET, PKT>(PKT primaryKey) where ET : IEntity2, new()
        {
            using (DataAccessAdapter adapter = new DataAccessAdapter())
            {
                ET entity = new ET();
                IList<IEntityField2> pks = entity.PrimaryKeyFields;
                pks[0].ForcedCurrentValueWrite(primaryKey);
                if(adapter.FetchEntity(entity))
                        entity.Fields.State = EntityState.Fetched;
                return entity;
            }
        }
Posts: 5
Joined: 01-Mar-2009
# Posted on: 02-Mar-2009 14:40:57   

Cool. I'll try that. Thanks!

Is there a way to do this that doesn't use ForcedCurrentValueWrite() since the description of the method says it's for internal use and users shouldn't be calling it?

thanks

Walaa avatar
Walaa
Support Team
Posts: 14993
Joined: 21-Aug-2005
# Posted on: 02-Mar-2009 14:50:26   

Well, I'll have to ask why are you doing your own generic function while you can use the adapter.FetchEntity(), which is generic too.

The problem is your method can never validate the type of the passed PK is actually the correct one to use with the passed entity type.

So it's better for the caller to create the entity, since he will be aware of the type, and simply call a wrapper to the FetchEntity() if you are encapsulating it, or call FetchEntity() directly.

Posts: 5
Joined: 01-Mar-2009
# Posted on: 02-Mar-2009 15:32:21   

Well, my app has a service layer and a repository layer. I have service layer classes calling into repository classes that map one-to-one to the tables in my schema. I realized I was creating the same Save() and Get() methods in each repository class, only differing by the entity being returned, so I figured genericized versions I could but in my repository base class would just clean up my code.

My Save<>() below works fine, so I wanted to add them for Get() and SaveCollection() as well.


public R Save<R>(R entity, bool refetch, bool saveRecursize) where R : IEntity2
        {
            using (DataAccessAdapter adapter = new DataAccessAdapter())
            {
                adapter.SaveEntity((IEntity2)entity, refetch, saveRecursize);

                return entity;
            }
        }

Oh, and I also know that my PKs are always guids for one part of the schema and ints for another part, so me passing in the wrong type isn't an issue for me.

thx