Wednesday, August 19, 2009

Corrupt TNSNAMES.ORA file

I just spent three hours troubleshooting this error: "ORA-12154: TNS:could not resolve the connect identifier specified." I had three TNSNAMES.ORA files with identical information. Oracle.DataAccess interaction with two of the three resulted in the ORA-12154 error. After scouring Google, I finally came across this nugget of wisdom:

Just a note, sometimes the TNSNAMES.ORA will get messed up. Nothing will jump out but it will not work and you cannot see the file though the net config. Just re-create it using notepad or [s]omething.

I replaced the two misbehaving files with the 'good' file and guess what? ORA-12154 magically went away.

Wednesday, August 5, 2009

ClickOnce and NHibernate

I've been working on a WPF MVVM intranet application that uses NHibernate for data access. As I expected, the initial ClickOnce deployment failed due to a missing configuration file and Castle assemblies. My View project used a Post-build event to get the required NHibernate files so that everything would run smoothly. Here's what that command line looks like:


C:\Windows\Microsoft.NET\Framework\v3.5\MSBuild.exe
   "$(ProjectDir)DeploymentUtil\CopyNHibernateStuff.xml"
   "/p:TargetCompileDirectory=$(TargetDir);TargetProjectDirectory=$(ProjectDir)"


Originally it just used the $(TargetDir) macro as an input to an MSBuild project file to copy the NHibernate files to the bin\Debug directory. In consideration of ClickOnce I modified it to also use the $(ProjectDir) macro to copy the files to the View project's root directory. Here's the contents of the CopyNHibernateStuff.xml file:


<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<TargetCompileDirectory>.</TargetCompileDirectory>
<TargetProjectDirectory>.</TargetProjectDirectory>
<HibernateCfgPath>C:\SourceTfs\Patient Safety Organization\Eligibility Manager\PsorgEligibilityData\hibernate.cfg.xml</HibernateCfgPath>
</PropertyGroup>
<ItemGroup>
<NHFiles Include="C:\Program Files\NHibernate\Required_For_LazyLoading\Castle\Castle.Core.dll" />
<NHFiles Include="C:\Program Files\NHibernate\Required_For_LazyLoading\Castle\Castle.DynamicProxy2.dll" />
<NHFiles Include="C:\Program Files\NHibernate\Required_For_LazyLoading\Castle\NHibernate.ByteCode.Castle.dll" />
<NHFiles Include="C:\Program Files\NHibernate\Required_For_LazyLoading\Castle\NHibernate.ByteCode.Castle.pdb" />
<NHFiles Include="$(HibernateCfgPath)" />
</ItemGroup>
<Target Name="CopyNH">
<Message Text="NHFiles: @(NHFiles)" />
<Message Text="TargetCompileDirectory: $(TargetCompileDirectory)" />
<Copy SourceFiles="@(NHFiles)" DestinationFolder="$(TargetCompileDirectory)" />
<!-- Now copy files (again) to project directory so that they can be referenced as a publishable file by ClickOnce. -->
<Copy SourceFiles="@(NHFiles)" DestinationFolder="$(TargetProjectDirectory)" />
</Target>
</Project>


I did some spelunking in the View project file to determine how items appeared in the Application Files dialog on the Publish tab. I figured out that I could manually add my required NHibernate references in the following manner and they would be available to ClickOnce for publishing.


<ItemGroup>
<Content Include="hibernate.cfg.xml" />
<Reference Include="Castle.Core.dll" />
<Reference Include="Castle.DynamicProxy2.dll" />
<Reference Include="NHibernate.ByteCode.Castle.dll" />
</ItemGroup>


Of course after I did all of this work I discovered this post which described my process in detail. At least it confirmed that I wasn't terribly abusing MSBuild.