Oracle gets decorated by Microsoft… with an Obsolete Attribute

About a week ago Microsoft announced that the System.Data.OracleClient namespace will be deprecated in .Net 4.0. However the fact is that “deprecated” doesn’t mean it will disappear completely anytime soon. In fact the official statement clearly states the following:

Microsoft will continue to provide hotfixes for critical issues in System.Data.OracleClient as per the standard support policy for .Net Framework 4.0. We will also continue to make critical bug fixes in future service packs for .Net Framework 4.0.

So it will probably hang around for another 8-10 years so your old application doesn’t have to be updated for some time yet. But you probably don’t want to write new .Net 4.0 applications with it. Instead you should probably search for third-party providers.

So why is Microsoft making this move?

Some evil tongues may claim that Microsoft is simply just bored with developing for their competitor, and maybe they are, but that’s not the whole truth. Microsoft have always encouraged their partners and others to provide third-party solutions for their development tools and languages. The official statement also says:

We learned that a significantly large portion of customers use our partners’  ADO.NET providers for Oracle;  with regularly updated support for Oracle releases and new features. In addition, many of the third party providers are able to consistently provide the same level of quality and support that customers have come to expect from Microsoft. This is strong testament of our partners support for our technologies and the strength of our partner ecosystem.  It is our assessment that even if we made significant investments in ADO.Net OracleClient to bring it at parity with our partners based providers, customers would not have a compelling reason to switch to ADO.Net OracleClient.

This is probably true, but I don’t believe that this fact is the complete reason for this decision. Microsoft is now pushing the Entity Framework (and it’s light-weight cousin: LINQ to SQL) and there have never been any promises from Microsoft about any EF support for Oracle. However Oracle themselves have made promises about that, but according to a recent blog post by Julie Lerman (a fellow MVP and the author of the excellent book Programming Entity Framework) this doesn’t seem to happen very soon:

Oracle continues to promise their EF support, though there is still a wait and wonder policy on their end. Their .NET guy, Christian Shay (who spoke at DevConnections in the Data Access track last November) has not updated his blog since September.

Julie also said that DataDirect recently refreshed their beta of Connect for ADO.NET Entity Framework provider for Oracle.

What does this mean for you and me?

As I mentioned earlier, “deprecated” does not mean “deletion”. You can probably continue to support your old applications that uses the OracleClient for many years yet. But consider using a third-party provider for new .Net 4.0 applications. For myself, this doesn’t effect me at all since at my current position at Interactive Medica we use SQL Server and I don’t mind using third-party tools for new development if needed.

pimp itkick it on DotNetKicks.com

Using the CodeDom to do scripting with .Net

Introduction

The company I work for, Interactive Medica, provides SaaS business solutions for the pharmaceutical industry. Many of our clients receive data from third-parties which they need us to import into our system. This is pretty straight-forward and common in many industries. The data arrives in different formats, CSV files (or other delimited text files), Access database, Excel Spreadsheets, and so on. Sometimes the files are zipped and sometimes not. Sometimes the files are uploaded to us via FTP and at other times we need to pull the data, also usually via FTP.

Any developer have at some time or another been acquired to do something like the above, shuffling data from one source to another. Luckily, using ADO.Net, it’s not very hard to do so, as long as you have the correct connection string. Anyhow, when I first started at IM they only had a few of these import programs, which all worked but the problem was that they were all hard coded, by which I mean that any changes made to the file that needed to be imported meant that we had to open up the source code for the import program and make the changes, recompile and deploy it back to the server. This was more than tedious. Some of them were also rather old, written in VB6 in a VBScript style manner, meaning no Option Explicit, new variable names created at the fly and the developer seemed to think that reusing one variable more than once wasn’t necessary when you could create a new one, all with nifty names like Foo, Q, P, S1, M12, and so on that didn’t give a clue at what they contained or was used for. Global scooping also apparently seemed like a good idea, and of course the original developer had since long left the building (the company).

OK, I’m sorry since this wasn’t supposed to be yet-another-ranting about the perils of maintaining old proprietary code. When I was asked to create a new handful of import tools I was determent to make them easier to maintain. What I wanted to do was to create a number of classes that contained all method necessary to do the importing regardless of the data source. All information about the file and where it should be imported to would be in a config file, easily editable without the need to open up the source code. When all this was done, I educated my colleague, that are responsible for monitoring these tools, on how to use them. He isn’t a developer but he does know some VB, and using the framework I created he’s been able to create new import tools by himself.

What I didn’t realize then was how the number of necessary imports was going to grow, and grow fast. The problem is that I never created one program that could use different config files at different points in time. So the program had to be copied, sometimes changed a bit for a new customer import, and deployed as a new EXE file that run on the server at scheduled points in time. I think that we now have around 40 almost identical programs running on the server. So now they are also starting to be a mess to administrate and maintain. So it’s pretty obvious that something needs to be done.

Already two years ago when I first created this import tool framework I was thinking that this should really be done with some clever scripting language. Whenever a change is made in the file that we need to import we could simply open up the script in any text editor make the necessary changes and save it again without the need to launch Visual Studio on my local machine, check out the source code from our source control system, make the changes, test, build and compile it, check in the source and deploy the application on the server. Well, several choices are available. I could have used cool stuff like Python or even PHP but, no that would require their runtimes to be deployed on the server… Not a biggy you say, well it is when it’s going up on a live environment. It have to be lab tested first, with all kind of rigorous evaluation, new documentation have to be written and approved and all that. There was just not time for anything like that since our customer wanted the information yesterday. What we already have on the server is the .NET framework, live with it chump. OK, so how about scripting for .NET then? Well, we always have VSA (Visual Studio for Applications) but that requires a lot of work. Another quicker solution is to use System.CodeDom and reflection, so that’s the path I choose.

Creating the contract

The System.CodeDom.Compiler namespace contains the abstract class CodeDomProvider from which language specific providers inherits. In my case I’m interested in the VbCodeProvider which resides in the Microsoft.VisualBasic namespace, you could also use the CSharpCodeProvider if you wish. The namespace also contains the CompilerParameters class with which you would set, yes you guessed it, parameters necessary to compile the source into an assembly. I will get to these classes shortly, but first let’s have a look at how we would create a contract between a script file and the scripting engine that we will use to run the script. To keep it as simple as possible I created a new Class library project which I named Scripting. This library only contain an Interface with one single method called ScriptMain() which all scripts must implement.

Public Interface IScriptable
  Sub ScriptMain()
End Interface



With that in place a minimal script that does absolutely nothing would look like this:



Public Class MyScript
  Implements Scripting.IScriptable

  Public Sub ScriptMain() Implements Scripting.IScriptable.ScriptMain
    'script code goes here
  End Sub
End Class



Using the CodeDom



Now for the fun part. How to run the script. For the sake of this article I’m going to create a small demo application, consisting of a Windows Form with one button and a multi-line textbox.



image



You would write the script in the textbox and hit the button to run it. To this project I also add a class we will name ScriptEngine. I also added a reference to the above mentioned class library containing our interface. The ScriptEngine class will import the System.CodeDom.Compiler and the System.Reflection namespaces plus our Scripting namespace containing the IScriptable interface.



As I mentioned earlier I’m going to use the VBCodeProvider to compile the script. By default the provider will compile the source to a .Net 2.0 assembly. To be able to use version 3.5 of the .Net framework we need to supply some provider options to the constructor of the class.



Dim providerOptions = New Collections.Generic.Dictionary(Of String, String)
providerOptions.Add("CompilerVersion", "v3.5")
Dim provider As New VBCodeProvider(providerOptions)



Now that we have our code provider we must also add some parameters. The compiler parameters tell the provider how we want our assembly to be built. In our case we do not want to create an executable file but instead just create an in memory assembly. We also want to add references to some other commonly used assemblies like System.Windows.Forms and others, most importantly we add a reference to our Scripting.dll which contains the IScriptable interface. To be able to add this class library it either have to be added to the GAC or exist in the same folder as our executable (I use the latter). We can also provide some compiler options like Option Explicit, note that the /OptionInfer flag can only be used if we use the v3.5 Framework compiler.




Dim parameters As New CompilerParameters
With parameters
  .GenerateExecutable = False
  .GenerateInMemory = True
  .IncludeDebugInformation = False
  .ReferencedAssemblies.Add("System.dll")
  .ReferencedAssemblies.Add("System.Windows.Forms.dll")
  .ReferencedAssemblies.Add("Microsoft.VisualBasic.dll")
  .ReferencedAssemblies.Add("Scripting.dll")
  .CompilerOptions = "/OptionExplicit+ /OptionStrict- /OptionInfer+"
End With



OK, we now have everything set up to compile an assembly out of our script. The CodeDom provider have a number of methods to do this, for example CompileAssemblyFromFile() or CompileAssemblyFromSource(). In this demo we don’t have any source file stored on our hard drive so we will use the latter of these two methods that accepts a string as the source. As a matter of fact it actually accepts a ParamArray of strings if we would have several sources of code that we wanted to compile into the same assembly.



Dim result As CompilerResults
result = provider.CompileAssemblyFromSource(parameters, source)



As the first argument we pass the CompilerParameters we just created and then the string containing our source code. If the returned CompilerResults doesn’t contain any compiler errors we are ready to run our script.



If Not result.Errors.HasErrors Then
  Dim script As IScriptable = FindScriptable(result.CompiledAssembly)
  If script IsNot Nothing Then
    script.ScriptMain()
  End If
End If



Here we call a little helper function named FindScriptable() that uses reflection to find a reference to our IScriptable interface that our script had to implement. If found we simply call the ScriptMain() method to run our script.



The full source code for our script engine will look as follows:




Imports System.CodeDom.Compiler
Imports System.Reflection
Imports Scripting


Public Class ScriptEngine
  Public Function RunScript(ByVal source As String) As Boolean
    Dim providerOptions = New Collections.Generic.Dictionary(Of String, String)
    providerOptions.Add("CompilerVersion", "v3.5")
    Dim provider As New VBCodeProvider(providerOptions)
    Dim parameters As New CompilerParameters
    With parameters
      .GenerateExecutable = False
      .GenerateInMemory = True
      .IncludeDebugInformation = True
      .ReferencedAssemblies.Add("System.dll")
      .ReferencedAssemblies.Add("System.Windows.Forms.dll")
      .ReferencedAssemblies.Add("Microsoft.VisualBasic.dll")
      .CompilerOptions = "/OptionExplicit+ /OptionStrict- /OptionInfer+"
    End With
    Dim result As CompilerResults
    result = provider.CompileAssemblyFromSource(parameters, source)
    If Not result.Errors.HasErrors Then
      Dim script As IScriptable = FindScriptable(result.CompiledAssembly)
      If script IsNot Nothing Then
        script.ScriptMain()
        Return True
      Else
        Return False
End If Else Return False End If End Function Private Function
FindScriptable(ByVal assembly As Assembly) As IScriptable For Each t As Type In assembly.GetTypes() If t.GetInterface("IScriptable", True) IsNot Nothing Then Return DirectCast(assembly.CreateInstance(t.FullName), IScriptable) End If Next Return Nothing End Function End Class







Now all that is left is to call the RunScript() method from our little editor. So in the Click event of the button I have the following code:



Dim engine As New ScriptEngine
engine.RunScript(TextBox1.Text)



In this simple demo the RunScript() method simply return true or false on success or failure. In a real application you probably want to get more information why the compilation of your script failed. In that case you can let the method return a CompilerErrorCollection instead. You get this collection from the CompilerResults class.



Return result.Errors



You can then loop through this collection and give information about each compiler error including the error message and the line the error occurred on.



Extending the script engine



You now probably want to add your own classes to the script engine. The easiest way of doing that is just to add your classes to the Scripting class library since we already add a reference to that in the script. I only used shared methods in my classes just to make the scripts easier to create, but you could do as you wish. To keep my scripts tidy of any extra “noise” I also simply required that the script contained a public sub called ScriptMain() so that it doesn’t even have the Class or the Implement IScriptable declaration in the script file. I simply add that to the source string before I pass it along to the CodeDomProvider.



I also used the ICSharpCode.TextEditor that is part of the SharpDevelop project to build my own custom IDE with syntax highlighting.



image



Happy scripting!


pimp itkick it on DotNetKicks.com

How to prevent Extension methods from appearing as global functions

C# have static (or shared) classes which VB lacks. Instead VB uses modules which are almost the same thing. One thing differs though and that is that modules makes its public methods appear as global accessible functions, meaning you don’t have to type the ModuleName.MethodName() when calling such a member. You can instead simply call MethodName() directly.


A disadvantage of this fact is that extension methods, that must exist in modules in VB, will appear in IntelliSense as global functions and not only as a method of the type you extended.


Let’s say you have the following:


Public Module ExtensionMethods
  <Extension()> _
  Public Function EqualsText(ByVal str As String, ByVal equalsTo As String) As Boolean
    Dim sc As New CaseInsensitiveComparer
    Return (sc.Compare(str, equalsTo) = 0)
  End Function
End Module


The above extension method allows you to do case-insensitive comparison of two strings in the following manner:


If myString.EqualsText("Hello world") Then
  'do something
End If


The above will be true if myString contains “HELLO WORLD”, “hello world”, or even “hEllO wOrLd”.


The problem is that this method will show up in intellisense even if you don’t use it as a member of a string.


image


However in this case you probably just want the EqualsText function to appear as a member of a string.


image


So is it possible to prevent this extension method from appearing as a globally accessible function?


The answer is yes. You decorate your module with the EditorBrowsable attribute (available in the System.ComponentModule namespace). This attribute is really meant to hide methods or properties from appearing in IntelliSense but it can be used at the class level as well. Note, I do not recommend using this attribute on modules that contain anything but extension methods since it effectively hides everything in that module. 


 


<EditorBrowsable(EditorBrowsableState.Never)> _
Public Module ExtensionMethods
  <Extension()> _
  Public Function EqualsText(ByVal str As String, ByVal equalsTo As String) As Boolean
    Dim sc As New CaseInsensitiveComparer
    Return (sc.Compare(str, equalsTo) = 0)
  End Function
End Module

Now EqualsText() will still appear as a member of a string but not as a global function.


kick it on DotNetKicks.com

What I don’t like about iPhone

A couple of weeks ago I caved in to peer pressure and got myself an iPhone 3G 16GB (probably very stupid since the 3rd generation iPhone is released next week). Before I tell you what I don’t like about this phone I should probably mention that I do love the iPhone, but nothing is ever so good that it doesn’t have room for improvements. I’m also aware that many of the things I will comment on here are being addressed in version 3 but I’m still amazed that some of these features are not available already.


OK, here’s the list:


  • Copy and Paste.
    Why in the name of everything that is holy didn’t the iPhone support Copy and Paste from version 1? Come on, I got my first Nokia phone in the early ‘90s and it had Copy and Paste back then.
  • MMS
    Que? A 3G camera phone that doesn’t allow me to send MMS? Come on…
  • On Screen Keyboard
    Why can’t I tilt the phone while writing a SMS and get the wide-screen keyboard layout like I can in the web browser? I have big fingers and want the slightly larger buttons I get that way. The same goes for typing notes, or adding appointments to the calendar.
  • Low resolution camera.
    This will only be slightly better in the next version, but come on, most new phones have at least a 5 megapixel camera, some have a lot more.
  • Video
    Since the camera itself is able to record video why wasn’t that available earlier?
  • True GPS
    While driving I need to hear the directions being read to me. I don’t always have a passenger beside me that can read them to me.
  • Step into text
    The magnifying glass that appears when you press and hold your finger over the text area you’ve just typed in is pretty cool but not very intuitive, it took me a while before I noticed and learned how to step back into a line of text to correct a typo without deleting everything I’d typed after it. I’ve also noticed that sometimes this magnifying glass appears in the wrong spot so that you actually don’t see where you put the text caret. This is especially true when browsing the web and typing in web forms.
  • I like that the on screen keyboard adopts itself when I type an address into the address field of the Safari browser. Replacing the space bar with three other buttons containing the period, slash, and a “.com” button. This is great since an URL can’t contain any spaces while dots and slashes are pretty common. Switching over to the numeric keyboard from here also shows less buttons than while typing anywhere else. Also a good idea, only show buttons with valid characters. However the thing is that parentheses are valid characters and some addresses do use them (IMHO a bad habit but still valid) but there are no parentheses buttons on the keyboard.
  • BUG!
    Sometimes, granted not very often, after synchronizing the phone with iTunes all downloaded applications stops working. They might show their splash screen and then simply die. When that happened to me I did a Google search and found that many others had had the same problem… Some of them going back more than a year back. Why haven’t this been fixed with new updates to iTunes? Is it just because Apple have the motto: It just works (and when it doesn’t we don’t want to hear about it).

Windows 7 = Windows 6.1

I was rather confused when I first heard that Microsoft was going to call the new version of Windows for Windows 7 since in my mind it’s Vista that should have been version 7.

The first version of Windows NT got the version number 3.1 to align with the 16-bit version of Windows. Later there where a 3.5 and a 3.51 version of NT before the release of NT 4. After that came Windows 2000, which was Windows 5. Then Microsoft released XP which I thought should have been version 6, but the version number was set to 5.1 even though it was very unlike Windows 2000.

Instead Vista got the version number 6, even though I think it should have been 7. Now Windows 7 release candidate is available for download. The main difference between Vista and Windows 7 is the new taskbar and not much more (well, there are a bunch of other goodies under the hood, but from a user perspective the taskbar is the main noticeable difference) so in a sense it should really be Windows 7.1 since I think Vista should have been version 7. But lo and behold, the version number in Windows 7 is 6.1 and not 7.

Console.WriteLine(System.Environment.OSVersion)



Go figure.