Friday, July 30, 2010

Attaching detached objects to NHibernate session

While I was developing for my customer I suddenly received a NonUniqueObjectException while deleting some data.

NHibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: 58372, of class: …

The problem I suffered from was that I was deleting the “same” object twice. The issue is that NHibernate knows that these objects are the same, although the objects have different object references.

One of my objects was a detached object that came from and was deleted in the GUI. The second object came from a fetch of data to fill a non-mapped collection. The objects in this collection have a reference to the object we want to delete. Because this reference was mapped, an instance of this object is fetched from the DB.

So when this collection is fetched, and then we try to delete the detached object, we receive the NonUniqueObjectException. The solution for this is to find a way to attach the detached object to the NHibernate session before I fetch the collection. But when you look for it into the IDaoPersister interface, you won’t find any “Attach'” method.

After some quality time spent on Google I discovered the following in the Hibernate documentation:
http://docs.jboss.org/hibernate/core/3.3/reference/en/html/objectstate.html#objectstate-detached

Use update() if you are certain that the session does not contain an already persistent instance with the same identifier. Use merge() if you want to merge your modifications at any time without consideration of the state of the session. In other words, update() is usually the first method you would call in a fresh session, ensuring that the reattachment of your detached instances is the first operation that is executed.

This means you can use the update() method to reattach your detached objects to the session. The update() method won’t trigger any update queries to the DB. These update queries will only be executed when the Flush() method is called on the session and NHibernates discovers properties that have been changed on the object.

Conclusion

Before I retrieve my collection I call the update() method with my detached object as parameter. This way the object is stored in the NHibernate cache and won’t be retrieved from the database when needed.

Monday, July 19, 2010

Browse online your Windows Azure Storage account

MyAzureStorage

The Windows Azure MyAzureStorage is a web based application that gives you the ability to browse your Windows Azure Storage. There are 3 available browsers: a TableBrowser, a QueueBrowser and a BlobBrowser. The only thing you need to logon to the application is your storage account name and your primary access key.

This is an official Microsoft application, so you can trust this, but be careful when giving your storage account name + primary access key away. With this information, people with bad intentions can access your Azure storage account and modify it.

TableBrowser

MyAzureStorageTable

In the TableBrowser you see a list that represents all the tables stored in your storage account. Besides viewing, you have the ability to create new and delete existing tables, and when you click on one of the table names, you navigate to the content of the the table.

MyAzureStorageTableContent

Just above the list with the content you have a textbox you are able to query the table content with a simple SQL like syntax. Some example queries:

  • Filter on Partition Key: PartitionKey = “PartitionKeyValue”
  • Filter on Row Key: RowKey = “RowKeyValue”
  • Filter on Columns: ColumnName = “CellValue”

=, !=, <, >, <=, >= are the operators you can use to query and there is also a possibility to combine multiple filters with AND, OR or NOT.

Into the left of the list, you see an summary of al the columns that are present in the table. By checking them you make them visible or invisible in the result set.

Besides viewing the data, there is the possibility to create, edit, copy and delete an entity. While creating, editing or copying an entity, you have the ability to add new properties.
When you make a copy of an entity, all properties get copied, except the RowKey which needs to be unique in the combination with a PartitionKey in the table.

QueueBrowser

MyAzureStorageQueue

In the QueueBrowser you receive a list of all the available queues in the account. You have the ability to create queues, edit the metadata or delete queues. When you click on one of the queue names, you navigate to the content of the the queue.

MyAzureStorageQueueContent 

In the content of the queue you are able to add new messages or clear the entire queue. The manually created messages will get an expiration time that is 7 days later than the insertion time.  When viewing the content the data gets peeked, so you don’t have to worry that you’re messages should get unavailable.

BlobBrowser

MyAzureStorageBlob

In the BlobBrowser you receive a list of all the blob containers available in the account. You are able to create or delete an blob container. Other actions are:

  • Editing: you can set the Public access (Off / Container level / Blob level) and the metadata of the container.
  • Manage policies: you can create, edit or delete your access policies for the container. A policy has a name, a start date, an end date and RWDL (Read, Write, Delete, List) rights.
  • Share: you can create an url with limited access for the users who access it. You can do this based on a policy or with a start date, end date and RWDL rights.
  • Add Blob: adds a blob to the container.

MyAzureStorageBlobContent

When we click on a container name, we get a list with all the blobs within the container and if we click on one of these blobs, we get to see the details as shown on the image above. On the blob we can take the following actions:

  • Edit: you can upload a new file to the blob or change the metadata of the blob
  • Copy: makes a copy of the blob in on of the available containers.
  • Download: you can download the blob.
  • Share: you can create an url with limited access for the users who access it. You can do this based on a policy or with a start date, end date and RWDL rights.
  • Delete
  • Create new snapshot: you can make a snapshot based on the current state of the blob.

Monday, July 12, 2010

Be careful with CreateTablesFromModel

I started with the Windows Azure by following an online course of UK Dev. This course was a compilation of reading white papers, following recorded sessions and the Windows Azure Labs. While working with these labs, I wanted to start from scratch instead of using the start solution.

So I started to set up the N-tier solution and added all the necessary references. I created the whole solution as described in the lab, but I used my own naming convention. When everything was set-up I pressed the F5 button and the application started. So far, so good. The web form started, I filled in my web form and pressed the save button to persist my data… and received a DataServiceRequestException.

In the Inner Exception I was able to discover a little more information:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
<code>TableNotFound</code>
<message xml:lang="nl-BE">The table specified does not exist.</message>
</error>

At this stage I was surprised. The CreateTablesFromModel method didn’t give me any notice that something went wrong while creating my model. So I went looking in the development storage database what was missing. In the TableRow table I discovered that a row was added, but the name in the column ‘TableName’ wasn’t the name that I was expecting. I named my domain class ‘Entry’ but in the row that was added, the table name was ‘Entries’.

So I went looking in my code for the name ‘Entries’ to find out that I had a property called ‘Entries’ in the implementation of my own DataContext.

/// <summary>
/// Exposes the Entry table
/// </summary>
public IQueryable<Entry> Entries
{
get
{
return this.CreateQuery<Entry>("Entry");
}
}

I presumed that my tables would be created by the name given to the class that persists the data. However, the names of the properties in the DataContext are used to create the table names. At this point I had 2 possibilities:
· I rename the property in the DataContext to ‘Entry’
· I change the string parameter in the CreateQuery method inside the property to ‘Entries’
The last option meant that I would have to look up where else this parameter is used, so I can change it to ‘Entries’. (The AddObject method was one of the methods I had to change)

The start of My Blog

Hi all,

My name is Kristof Degrave and I am 24 years old. I am currently working as a .NET software engineer @RealDolmen.

Recently, I started to discover the Windows Azure platform, and this will be the main thread through my blog posts. Because the clouds are still a learning process for me, feel free to comment my posts.

I hope you will enjoy reading my blog and maybe even learn something from it.

Greetings,

Kristof