Sunday, September 26, 2010

How To Get Fluent NHibernate, NHibernate And Castle To Work Using Medium Trust

There are times when open source projects can give you incredible joy. Then there are other times when you just want to go find the developers of a particular open source project and yell at them just a little bit. The truth is that we should all be thankful that open source developers care enough to create fantastic open source projects, but sometimes things can get hairy and scary. I had one such situation with NHibernate, Fluent NHibernate, Castle and StructureMap when I tried to get everything working in a medium trust environment. I'm going to tell you how to solve the problem so that you can have an easier go of things than I had.


I created a beautiful project using NHibernate, Fluent NHibernate , the part of Castle that NHibernate relies on and StructureMap. Everything worked perfectly in development and I was super happy and all smiles. Instead of just releasing the project, I decided to create a coming soon page for it. The coming soon page can be seen here - http://www.thedesigncoders.com/comingsoon. That page has a contact form on it that uses NHibernate to persist the data. This page looked and worked great on my development machine, but I got a rude awakening after deploying it. That rude awakening was an error - System.Security.SecurityException: That assembly does not allow partially trusted callers. What? OMG! Here was the first lesson for me - always run your project on dev using the same trust level as your production environment. Doing this would have shown me the error well before deployment. OK. Lesson learned.

Now I was in a pickle. The error was occurring in Castle according to the error message. I used Google to investigate the issue. There were a whole lot of different things that people tried. One of them was to disable lazy loading. I nearly lost my lunch when I read that! I had set up Fluent NHibernate using its AutoMap feature and I had an EXTENSIVE database system with a lot of interconnected many to one, one to one and one to many relationships. Disabling lazy loading would basically mean that I might as well remove NHibernate and Fluent NHibernate and use Entity Framework. That, however, would have taken me a long time to do and it simply wasn't anything I even wanted to think about. I don't have anything against Entity Framework, but it took effort for me to set up NHibernate, Fluent NHibernate and StructureMap and I wasn't about to abandon my beautifully done project because of one stupid error. I was GOING to figure this out.

OK. So after viewing some blogs AND the NHibernate website, which suggested that I would need to go through hell and high water to get things to work, I decided to keep searching. Here are some of the articles I came across.


  1. Use NHibernate Proxy Generators
    http://nhforge.org/blogs/nhibernate/archive/2008/09/23/introducing-nhibernate-proxygenerators.aspx
    This would be good, but I'm using Fluent NHibernate's AutoMap feature so I don't use mapping files. That means that this is useless to me and it is likely unnecessary for you.

  2. Disable Lazy Loading, Disable Reflection Optimization & Change Web.Config Permissions
    http://nhforge.org/wikis/howtonh/run-in-medium-trust.aspx
    No, no and NOOOOOOOOOOOO!!!!!!! Fluent NHibernate's AutoMap feature makes things REALLY easy for me. If I had to disable lazy loading on my project given how large the database is and how much work Fluent NHibernate saves me from doing, I would have a fit. This just WAS NOT an option. In fact, it was a beyond useless idea to me.

  3. Rebuilding The Castle Project, NHibernate and Fluent NHibernate
    http://blog.yeticode.co.uk/2010/03/running-nhibernate-in-medium-trust/
    Hmmmm....this sounds good...... or so I thought! I would SIMPLY download all three projects, change the assembly in Castle to AllowPartiallyTrustedCallers, build it and use the dlls to then rebuild everything else. Great! I download the latest version of Castle and I start down that road. God/Allah/Jehovah/Jesus/Messiah/ HELP ME!!! It is times like these that make you feel stupid. I did all of that without thinking about ONE important (very important) thing - I didn't initially pay attention to the various versions of the files! Doooh!! Things did not match up! This version needed that version and that version needed this version and so on and so on. The problem wasn't JUST the versioning. Castle rolled its Dynamic Proxy into Castle.Core. It used to be its own project, but they changed this in the latest version. This meant that I had to change various parts of NHibernate. NHibernate was looking for a reference to Castle.Core AND Castle.DynamicProxy. I was starting to think about looking for a drink - and that says a lot because I have never had a drink of alcohol in my life! Fortunately, I figured out a different way.

I started thinking about the problem. The problem was that I couldn't set this project up on my chosen host because they don't allow people's apps to use full trust and the components I was using required full trust to do certain things. Surely I wasn't the only person who had this issue. In fact, I was positive I wasn't the only person with this issue because Google told me so (lol). Therefore, someone else had to have come up with a solution. I found that someone or a group of someones (I know this isn't proper grammar) had already solved the problem for their project. That project is called Cuyahoga. That brings me to solution number 4 -


    4. When In Doubt, Use The Files Of Someone Else To Work It Out! (I love that rhyme)

    Yeah! Now that is my kind of solution. After pulling out my hair by the root, this “solution” left me with 5 strands left! Cuyahoga is using NHibernate with Castle. Since they have already conquered the medium trust issue, I knew that their latest files should be sufficient for me. They don't use Fluent NHibernate (shame on them), but I knew that it would be nothing for me to download the latest source of Fluent NHibernate, add the dlls I took from Cuyahoga to the src and then compile everything. That is what I did and it worked like a charm. I swapped out the dlls in my project and I didn't have to disable or change anything else. Yes! Yes! Yes!

    Here is the link to the Cuyahoga files.

    https://cuyahoga.svn.sourceforge.net/svnroot/cuyahoga/trunk/lib

There you have it! Using those files will allow you to get everything running in a medium trust environment!


There are a couple of things that I found during my search that troubled me. There have been a lot of people who have had this issue. I would think that the open source project creators, especially NHibernate, would create source code that works in a medium trust environment. They won't. Making people do it themselves isn't necessarily a bad thing, but everyone doesn't want to spend time struggling to get things done. That is one of the things that makes Entity Framework appealing to the masses - for the most part, it just works.


Here is a link to one particularly onerous discussion surrounding the issue involving users and the Nhibernate developers. I found the whole character of the discussion to be completely distasteful. It shouldn't be so hard to do something that is so easy.

http://groups.google.com/group/nhusers/browse_thread/thread/dbfa6840d42f4c12/0db76f949568f947?lnk=gst&q=medium+trust#0db76f949568f947


If you have this issue, don't fret, worry or drive yourself insane. Just get those files and make it happen. Do not, I repeat, do not disable lazy loading for NHibernate to make it work in a medium trust environment. That defeats the whole purpose of the tool.

Smooches,

Kila

Friday, September 24, 2010

How To Tell What Happened When Publish Failed In ASP.NET MVC

This is a simple one. If you use the Publish feature in Visual Studio, you might be wondering how you can tell why a publish fails. The reason could be anything from an image file not being loaded in a project, to something more serious. To find out, you can click on View and then select Output to see exactly why the publish failed. Wasn't that simple?
Smooches,
Kila

Wednesday, September 22, 2010

How To Uninstall Internet Explorer 9 Beta

I made a mistake. I should have known better than to install a Microsoft Beta product. I love Microsoft, but their Beta products have some real quirks sometimes (I know....hence the term Beta). I usually wait - never wanting to be first in that arena. However, I decided to take a chance on Internet Explorer 9 Beta. The install SEEMED to go smoothly. The computer restarted, but I would get an error when I tried to use IE9. Every single time I clicked on it, I got the dreaded Windows has an error message and then Windows is checking for a solution message. Over and over. I tried all of the instructions provided by Microsoft to fix it, but I finally decided that I didn't and don't have the time to work through the issues. I need IE for development purposes and it HAS to work for me so I did an uninstall. However, when I went to do my uninstall, I couldn't find IE9! Since anything that is added has to have a way to be removed, I started searching to find it. I did and here is the solution so you won't have to spend as much time as I did.
On Windows 7 here is what you do:
  1. Go to Control Panel
  2. Select Programs And Features
  3. In the upper left hand corner, select View Installed Updates
  4. You will be provided with a list of updates, but you will likely not see Windows Internet Explorer 9 clearly in the list
  5. To find Windows Internet Explorer 9, go to the search box in the upper right hand corner and type in Windows Internet Explorer 9
  6. Windows Internet Explorer 9 will magically appear and you should select it and then hit the Uninstall button.
  7. The computer will uninstall the components and then ask you to restart.
  8. Once you restart, you will need to set up some attributes of Internet Explorer 8 again, but you will be rid of Internet Explorer 9 and ready to rock and roll.

Whew....lets not EVER do that again until IE9 is ready - lol!

Smooches,

Kila

Monday, September 6, 2010

How To Solve A SQL Server Database Marked As Suspect Mode

I'm going to keep this short and to the point. You may log into SQL Server some day and find that some of your databases have an exclamation point along with being marked with the following: DatabaseName (Suspect). That just makes you frown. Well I'm going to show you how to turn your frown upside down!

The solution is listed below.

Smooches,

Kila

Problem:
SQL Server marks your database as (Suspect). It won't open and you don't know what to do.

Solution:
To solve the problem, run the following in query analyzer.


EXEC sp_resetstatus 'YourDatabaseName';

ALTER DATABASE YourDatabaseName SET EMERGENCY

DBCC checkdb('YourDatabaseName')

ALTER DATABASE YourDatabaseName SET SINGLE_USER WITH ROLLBACK IMMEDIATE

DBCC CheckDB ('YourDatabaseName', REPAIR_ALLOW_DATA_LOSS)

ALTER DATABASE YourDatabaseName SET MULTI_USER

After you run this, right click on the database and hit Refresh. There you go! Now your frown is turned upside down!

Thursday, September 2, 2010

Primary Keys Do Not or Should Not Equal Clustered Index....Repeat After Me...Learn How To Add A Clustered Index On A Non Primary Key Column

Today I'm going to tell you about a novel concept that I just had to demonstrate to one of my employees who didn't know/believe that it was possible. Before I tell you about this concept, I need to give you a little bit of background information. If you are using SQL Server, you know that when you create a table and add a primary key, a clustered index is automagically created for you on the primary key column. However, the problem with that is that the primary key you create may not be the clustered index you are looking for. There can be only one clustered index on a table. SO what are YOU going to do if the clustered index on your primary key is not on the column you want? What are you going to do if you need to add a clustered index on a column that is not the primary key? The answer to those questions is to change the clustered index first and then create your primary key. In order to change your clustered index, you need to remember a few things.


  1. A primary key is not an index. Primary keys uniquely identify columns in your table - nothing more and nothing less. You don't have to use them for indexing.
  2. A clustered index, reorders the physical rows of your table. So if you are consistently doing searches on a particular column AND it is unique in your table, you can use that column in a clustered index. Don't forget this. I always use the example of a telephone book. Clustered Indexes are like telephone books. Why would you want to have a telephone book ordered by a randomly generated Primary Key? The answer is that you wouldn't. Instead, you need a real world way to order your information.
  3. You SHOULD NOT let SQL Server decide the clustered index for you. It happens by default, but accounting for this is part of good database design.
  4. Setting up a clustered index that IS NOT your primary key is easy to do.

I love #4.... I love #4....repeat after me....

So with all of those things in mind, let me give you an example. Lets say that you have a table called Options. Your table is defined like this.



CREATE TABLE [dbo].[Options](
[OptionId] [uniqueidentifier] NOT NULL CONSTRAINT [DF_Options_OptionId] DEFAULT (newid()),

[OptionName] [nvarchar](200) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,

[OptionDisplayName] [nvarchar](200) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,

[OptionDescription] [nvarchar](max) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,

[OptionStatus] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL CONSTRAINT [DF_Options_OptionStatus] DEFAULT ('ACTIVE'),

[LastStatusChangeDate] [datetime] NOT NULL CONSTRAINT [DF_Options_LastStatusChangeDate] DEFAULT (getdate()),

[CreatedBy] [uniqueidentifier] NOT NULL,

[DisplayOrder] [int] NOT NULL,

[DateAdded] [datetime] NOT NULL CONSTRAINT [DF_Options_DateAdded] DEFAULT (getdate())

) ON [PRIMARY]



Here is what this table looks like in the flesh without a key:


Looks good right? Now what? Well if you are like most people, your next step is to add the primary key! But this isn't correct. Adding the primary key will automatically create a clustered index. INSTEAD, we are going to create the clustered index FIRST! That's right! I said FIRST! You create the clustered index first and then you add the primary key after the fact.

Here is what you end up with.

You didn't see it, but the table is now physically ordered by the Display Order column - NOT the OptionId column. As you can see, we have a Clustered Index AND a Primary Key column which is unique, yet non-clustered. How did we do that? We did it by remembering to do the following:

  1. Create your Clustered Index FIRST - before you add a Primary Key!
  2. Add your unique Primary Key after you have added the Index.

This will allow you to have the clustered index set on the column that you actually should have it on instead of using the default set up that SQL Server offers you.

Problem:
You don't know how to add a non primary key column as a clustered index in SQL Server.

Solution:
Add the clustered index first on the column the table should be ordered on and then add the primary key.

* Note - Always remember to add your Clustered Index and then save and then add your primary key and then save AND THEN add your relationships. If you are using the SQL Database Diagram feature, don't try to add your clustered index and then use the diagram to add your primary key and relationships without saving the primary key BEFORE YOU ADD RELATIONSHIPS. If you add the clustered index and then go to the diagram to add the primary key and relationships WITHOUT SAVING the primary key before you add the relationships, when you save the primary key and relationships, the system will remove your custom clustered index and try to add the clustered index on the primary key only. This seems to be a quirk of using the database diagram feature.

Always remember the order -
  1. Add clustered index on your column
  2. Save
  3. Add primary key
  4. Save
  5. Add relationships
  6. save

Smooches,

Kila Morton