Monday, October 24, 2011

Featuring GXpowerCommands

apgetwikiimageAfter @gmilano’s Cool Commands for Visual Studio I thought I should write my own “cool commands” for Genexus. There a few tasks the I need to do quite often and I thought I’d be great if I could have right there on a contextual menu, like completely deleting a folder and it’s content or “Rebuild and run” an object… or even run (execute) an object as is, no further specification of analysis needed.

So I created this package with the extensions I found useful to myself. Here’s a little description of every command:

Empty and delete folder: I tries to delete every object in a folder and the folder itself. The success will depend on the references the contained objects have to. I any object A outside the selected folder) is referencing an object B from the folder, B won’t be able to be deleted, thus, the folder either. This command is not transactional.
Build/Rebuild folder objects: Ever wanted to build every object in a folder? It’s kind of painful to select every single object, right? Now you can step on a folder and choose to build or rebuild every single object in it.
Rebuild and run: Only valid for main objects, this command will execute a forced build (rebuild) and then execute (run) the generated program.
Run as is: What was that message again? I know the state of the generated program, I just want to execute it, no validation needed. This is the command that will fire the browser and show you the program “as is”. 
Command prompt here: This is a command that’s now built-in in Visual Studio. Applied to Genexus you can open a command prompt at the Knowledge Base directory or at your different environments directories. Just click on the desired node from the Preferences tree and voilá.
Windows Explorer here: Same as command prompt but for Windows Explorer. Enough said.

This package can be freely downloaded from the Genexus Marketplace, so go ahead and give it a try.

In this post I’ll like to answer the question I know some people must be wondering: “dude! you work at the Genexus Development Team, why aren’t these commands available in Genexus out of the box?”. Well, I’m no traditional Genexus developer so I’m not sure if these commands will actually be useful to the entire community so I don’t want to add “noise” to the already pretty big menus we have in Genexus. So depending on the adoption of these commands you might see some of them in Genexus in the near future.

Spanish instructions here, download here.

Like every other set of bits from this blog, this extension is “Works on my machine” certified, but this one has actually been tested by the guys at the Genexus marketplace Smile
works-on-my-machine-starburst_3_thumb[1]

EDIT 25-Oct-2011: Genexus X Evolution 2 support is now available.

Read Full Post

Thursday, March 31, 2011

WCF RIA Services Compositions with Entity Framework

I haven't been working on anything outside Genexus, Deklarit and Genexus Server for a while, so when my friend Mateo asked to help him on a new project for a client of his, based on brand new Microsoft technologies, I was saying yes before the end of the sentence.

This blog post and probably some more to come will be related to our experience with Entity Framework 4, RIA Services 1 and Silverlight 4.

But in this particular case I wanted to blog about a problem we had with Compositions. Compositions are very useful when you have an Association where a Parent entity needs to have its children all the time.

The Update method of parent entities is a bit different than regular entities. I took the patter from this article (Compositional Hierarchies) but things didn’t work as expected. I have to add that “m generating POCO entities and using the Unit Of Work pattern so it wasn’t easy just copy and paste the code for the article. I posted a few questions to the RIA services forum and found out that that pattern exposed a bug :(

Fortunately I was redirected this post from Brett Samblament which described the new pattern to follow to write a fully functional UpdateParent method. But again, I can’t just copy and paste, so here’s the code I wrote for it. Also, by using generic, I’m able to call the exact pattern for every composition in my model, cool uh?!

public void UpdateParent(Parent parent)
{
EntityHelper.UpdateParentEntity(parent, ObjectContext.Parents, ChangeSet, ObjectContext);

foreach (Child child in ChangeSet.GetAssociatedChanges(parent, o => o.Children))
EntityHelper.UpdateChildEntity(child, ObjectContext.Children, ChangeSet, ObjectContext);

}


And my EntityHelper class has the following methods:



public static void UpdateParentEntity<T>(T entity, IRepository<T> repository, ChangeSet chgSet, IUnitOfWork oc)
where T : class
{
try
{
ObjectContext ctx = oc as ObjectContext;
repository.ObjectSet.AddObject(entity);

T originalEntity = chgSet.GetOriginal<T>(entity);

if (originalEntity == null)
ctx.ObjectStateManager.ChangeObjectState(entity, EntityState.Unchanged);
else
repository.ObjectSet.AttachAsModified(entity, originalEntity);
}
catch (Exception ex)
{
TraceManager.Error(string.Format("An error occurred updating a {0}", typeof(T)), ex);
throw;
}
}


public static void UpdateChildEntity<T>(T entity, IRepository<T> repository, ChangeSet chgSet, IUnitOfWork oc)
where T : class
{
try
{
ObjectContext ctx = oc as ObjectContext;
ChangeOperation change = chgSet.GetChangeOperation(entity);

switch (change)
{
case ChangeOperation.Delete:
if (GetEntityState(entity, ctx) == EntityState.Detached)
repository.ObjectSet.Attach(entity);
ctx.DeleteObject(entity);
break;
case ChangeOperation.Insert:
// do nothing
break;
case ChangeOperation.None:
ctx.ObjectStateManager.ChangeObjectState(entity, EntityState.Unchanged);
break;
case ChangeOperation.Update:
T original = chgSet.GetOriginal<T>(entity);
if (original == null) { throw new Exception("Update with no original value found"); }
if (GetEntityState(entity, ctx) == EntityState.Detached)
repository.ObjectSet.Attach(entity);
repository.ObjectSet.AttachAsModified(entity, original);
break;
default:
break;
}
}
catch (Exception ex)
{
TraceManager.Error(string.Format("An error occurred updating a {0}", typeof(T)), ex);
throw;
}
}


public static EntityState GetEntityState(object entity, ObjectContext ctx)
{
System.Data.Objects.ObjectStateEntry ose;
if (ctx.ObjectStateManager.TryGetObjectStateEntry(entity, out ose))
return ose.State;
else
return
EntityState.Detached;
}


I hope this helps someone clear the way… and I promise I’ll post more (and more often) about this.



As usual, this code is ‘works on my machine’ certified.



works on my machine



I never get tired of this Smile

Read Full Post