Dynamic Casting When Handling Entity Events

Posts   
 
    
briansp avatar
briansp
User
Posts: 17
Joined: 30-Sep-2005
# Posted on: 13-Jan-2006 17:19:57   

I'm using the Adapter scenario, and I want to complete some logging code I'm adding to my project, as well as add some security features. It seems like for a basic security implementation one can add security checking to an extended DataAccessAdapter and implement some checking to say (does this user in this role have the ability to save/fetch/delete entities of this type).

One problem I have is in the logging code. I want to log when various events happen such as a save, or delete. I also want to log in the entity itself when it was created it and who created it, as well as when it was last modified and who modified it. Since the notion of security principals in my applicaiton will not exist in the DB, I should implement this logic in my BL.

So here's what I need to do if I want to see if we're saving a new entity (this is simplified, since I don't want to perform these actions on the EventEntity that I use to actually save my log events).

public override void OnSaveEntity(IActionQuery saveQuery, IEntity2 entityToSave) { if (entityToSave.IsNew) { // Set the CreateDate and CreatedByUserId on this entity.

        }
        // Set the LastModifiedDate and LastModifiedByUserId on this entity.

        base.OnSaveEntity(saveQuery, entityToSave);

}

The problem is that in order to set properties on the entityToSave I need to cast it as the proper type. The way that I'm doing this currently is repetitive:

       switch ((EntityType)entityToSave.LLBLGenProEntityTypeValue)
        {
            case EntityType.DocumentEntity:
                logevent.EntityId = ((DocumentEntity)entityToSave).Id;
                logevent.EntityGuid = ((DocumentEntity)entityToSave).Guid;
                break; 
           [and so on]

Is there any way to fetch the real type of the entity that's being passed around here, and then cast IEntity2 to that type, or otherwise access and set its properties? I can do this with big fat case statements, but that leads to a lot of repetitive code, and as I add/change entities in my project it gets unwieldy.

sparmar2000 avatar
Posts: 341
Joined: 30-Nov-2003
# Posted on: 14-Jan-2006 18:20:47   

I can do this with big fat case statements, but that leads to a lot of repetitive code, and as I add/change entities in my project it gets unwieldy.

Briansp Have a look at 'Factory design Pattern'. This pattern was developed to addresses this specific issue.

briansp avatar
briansp
User
Posts: 17
Joined: 30-Sep-2005
# Posted on: 17-Jan-2006 21:05:51   

sparmar2000 wrote:

Briansp Have a look at 'Factory design Pattern'. This pattern was developed to addresses this specific issue.

Could you be a bit more specific?

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 18-Jan-2006 07:28:09   
briansp avatar
briansp
User
Posts: 17
Joined: 30-Sep-2005
# Posted on: 18-Jan-2006 19:38:41   

Walaa wrote:

I thought this link might help: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnbda/html/factopattern.asp

I was hoping for more specificity related to my question.

psandler
User
Posts: 540
Joined: 22-Feb-2005
# Posted on: 18-Jan-2006 20:12:57   

Are the fields in question specific to each type of entity, or uniform across all entities?

If they are uniform, you can access their fields by name:

logevent.EntityId = entityToSave.Fields["Id"]; logevent.EntityGuid = entityToSave.Fields["guid"];

You can also do this if you want to update specific fields on the entityToSave (or any IEntity2):

entityToSave.SetNewFieldValue("CreatedByUserId", [whatever User ID Value]);

I'm actually not sure which of these questions you are asking.

If the fields are not uniform between entities, you will likely need something like the switch statement you mentioned in your original post.

HTH,

Phil

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 19-Jan-2006 07:38:31   

Hi Brian,

I think we may have miss-understand your question.

So to sum it up, In the OnSaveEntity() you want to know which entity is being saved? right

If it's just so, you may loop on the fields to get the fields with names you want.

for(int i = 0; i < entitySaved.Fields.Count; i++)
{
EntityField2 field = (EntityField2)entitySaved.Fields[i];
if (field.Name.ToLower() == "ID")
{
// use field.CurrentValue
}
}
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39930
Joined: 17-Aug-2003
# Posted on: 19-Jan-2006 09:50:59   

If you want to ALTER the same entity that's saved, use an override of OnBeforeEntitySave. OnSaveEntity is called right before the entity is saved and the query is already created.

Frans Bouma | Lead developer LLBLGen Pro
briansp avatar
briansp
User
Posts: 17
Joined: 30-Sep-2005
# Posted on: 19-Jan-2006 15:40:10   

psandler wrote:

Are the fields in question specific to each type of entity, or uniform across all entities?

If they are uniform, you can access their fields by name:

logevent.EntityId = entityToSave.Fields["Id"]; logevent.EntityGuid = entityToSave.Fields["guid"];

You can also do this if you want to update specific fields on the entityToSave (or any IEntity2):

entityToSave.SetNewFieldValue("CreatedByUserId", [whatever User ID Value]);

I'm actually not sure which of these questions you are asking.

If the fields are not uniform between entities, you will likely need something like the switch statement you mentioned in your original post.

Yes, this is what I was looking for. I didn't dig deep enough into the Fields attribute in the debugger to see that it had a deeper structure. Basically I want to mark my entities with when they're created and updated, and mark the system user that created and updated them. I'll also do some centralized logging to mark important operations. You can do this somewhat in the database, but the notion of a user principal exists in my app, not in the db, so the best way to do this is in my BL. I just wasn't sure how to get at the data in IEntity2.

My fields are uniform (Id, Guid, CreatedDateTime, CreatedByUserId, LastUpdatedDateTime, LastUpdatedUserId) across entities, so this should simplify my code a great deal.

Boy I love the debugger. sunglasses Thanks!

psandler
User
Posts: 540
Joined: 22-Feb-2005
# Posted on: 19-Jan-2006 17:01:55   

Otis wrote:

If you want to ALTER the same entity that's saved, use an override of OnBeforeEntitySave. OnSaveEntity is called right before the entity is saved and the query is already created.

Hmm, we override SaveEntity do do this. Everything seems to work fine with this. Any pressing reason to move it to OnBeforeSaveEntity?

Using 1.0.2004.2 is that makes any difference.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39930
Joined: 17-Aug-2003
# Posted on: 19-Jan-2006 18:14:43   

psandler wrote:

Otis wrote:

If you want to ALTER the same entity that's saved, use an override of OnBeforeEntitySave. OnSaveEntity is called right before the entity is saved and the query is already created.

Hmm, we override SaveEntity do do this. Everything seems to work fine with this. Any pressing reason to move it to OnBeforeSaveEntity?

Using 1.0.2004.2 is that makes any difference.

Correct, in 1.0.2005.1, save first calculates teh queue, then it persists the queue. THis means that it doesn't call itself recursively anymore, so overriding SaveEntity won't help, you have to move your code to OnBeforeEntitySave when upgrading to 1.0.2005.1.

Frans Bouma | Lead developer LLBLGen Pro