Getting Stock Prices: F# & NHibernate (1)

Ok. so now we a program that can retrieve stock prices and print them out.  But, what I really want to do is save them to a database.  So, let's see how to make F# work with NHibernate.  Let's start with something super simple.

First, I create a simple class (in VB 'cause I know it better)

------------------------------------------------------------------------- 

Option Explicit On

Namespace StockPrices

    Public Class COMPANY

        Private _ID As Integer
        Private _CompanyName As String
        Private _CompanyTicker As String

        Public Overridable Property Id() As Integer

            Get
                Id = _ID
            End Get

            Set(ByVal value As Integer)
                _ID = value
            End Set

        End Property

        Public Overridable Property COMPANY_NAME() As String

            Get
                COMPANY_NAME = _CompanyName
            End Get

            Set(ByVal value As String)
                _CompanyName = value
            End Set

        End Property

        Public Overridable Property COMPANY_TICKER() As String

            Get
                COMPANY_TICKER = _CompanyTicker
            End Get

            Set(ByVal value As String)
                _CompanyTicker = value
            End Set

        End Property

    End Class

End Namespace

------------------------------------------------------------------------- 

The class has only three properties: Id, COMPANY_NAME and COMPANY_TICKER.

I next create a SQL Server table that is iso-morphic to my class.

CREATE TABLE [COMPANY] (
 [Id] [int] IDENTITY (1, 1) NOT NULL ,
 [COMPANY_NAME] [varchar] (100) NOT NULL ,
 [COMPANY_TICKER] [varchar] (50) NOT NULL ,
 CONSTRAINT [PK_COMPANY] PRIMARY KEY  CLUSTERED
 (
  [Id]
 )  ON [PRIMARY]
) ON [PRIMARY]
GO

OK, now I can start to work in F#

I now a new project.

I first add a reference to my StockPrices class and also an open statement:

#light
open System
open System.Collections.Generic
open System.IO
open StockPrices

I now need to add references to FluentNHibernate and NHibernate (I do believe that you need both)

I then add two open statements into my code for FluentNHibernate

open FluentNHibernate.AutoMap
open FluentNHibernate

Now begins the work.

The first thing I do is declare a dictionary object to hold a set of configuration properties.  I then add a set of attributes.

let properties = new Dictionary<string, string>()

properties.Add("connection.provider", "NHibernate.Connection.DriverConnectionProvider")
properties.Add("dialect", "NHibernate.Dialect.MsSql2000Dialect")
properties.Add("connection.driver_class", "NHibernate.Driver.SqlClientDriver")
properties.Add("show_sql", "true")

let connString = "server='BIG_ROCK\LOGGERSEDGE';Initial Catalog=SMDATA;User ID=sa;Password=XXXXXX"
properties.Add("connection.connection_string", connString)

Not much to say here, other than I am using SQL Server 2000, so I have to tell nHibernate to use the MsSql2000Dialect.  I set my connection string and add it to my set of properties.

My next statement took forever to figure out:

let autoMappings = (AutoPersistenceModel.MapEntitiesFromAssemblyOf<StockPrices.COMPANY>()).Where(fun t -> (t.Namespace = "StockPrices.StockPrices"))

The point of this statement is that I want FluentNHibernate to map my Company class object and my database table automatically, obviating the need for a mapping interface xml file.

This part:

let autoMappings = AutoPersistenceModel.MapEntitiesFromAssemblyOf<StockPrices.COMPANY>()

says map my object StockPrices.COMPANY to the database.  I then need to add a where clause that tells FluentNHibernate  what namespace to use.  You should check out the FluentNHiernate site to get a more technical understanding of what is going on in the background.

My first hang up:

I discovered I need to wrap this:

AutoPersistenceModel.MapEntitiesFromAssemblyOf<StockPrices.COMPANY>()

in parentheses like this:

(AutoPersistenceModel.MapEntitiesFromAssemblyOf<StockPrices.COMPANY>())

in order to get intellisense to work.  Also, it generated this convoluted error:

"Successive arguments should be separated by spaces or tupled, and arguments involving function or method applications should be parenthesized"

It took me a while to figure out what this meant.  I guess I must be stupid.  Anyway, the where clause:

.Where(fun t -> t.Namespace = "StockPrices.StockPrices")

is an anonymous or lambda function.  The function returns true if the Namespace of an Entity equals the fully qualified name "StockPrices.StockPrices" where my class resides.  )Note:  I use the name StockPrices for both my assembly name and my Namespace -- you need to use both.)

F# provides a way to define a nameless function using the keyword fun. This type of function receives just one input value and returns just one output value.  Generally, if a function is to be passed as an argument to another function (as in the case here), then often you don’t need to give it a name of its own. These functions are referred to as anonymous functions and sometimes called lambda functions or even just lambdas.

The guts of the function above:

t.Namespace = "StockPrices.StockPrices"

 could have just as easily have been written:

if t.Namespace = "StockPrices.StockPrices" then true else false

but that would not have been as cool.

According the the FleuntNHibernate authority, James Gregory:

"...so I’ll introduce one final method: Where(Func<Type, bool>).

The Where method takes a lambda expression which is used to limit types based on your own criteria. The most common usage is limiting based on a namespace, but you could also look at the type name, or anything else exposed on the Type object."

Note that "Namespace" is a property of the Type object.

This is all a very long winded explanation as to why you need the Where clause in order for FluentNHibernate to just map those entities that you want mapped.  Also, my app crashed and burned without it.

My next line:

let aConfig = (new NHibernate.Cfg.Configuration()).AddProperties(properties).AddAutoMappings(autoMappings)

does quite a bit of work: It

(1)  Instantiates an NHibernate Configuration;
(2)  Add my dictionary lit of properties to the Configuration; and most importantly
(3)  Adds my autoMappings

Again, according to Gregory, AddAutoMappings substitutes for AddAssembly (used in regular NHibernate). This allows us to stop NHibernate from looking for hbm.xml files, and use our auto mapped entities instead.

The next block of code opens a NHibernate session and looks up AT&T in my database.  It then prints the company name and ticker to the console, giving us the gratification of knowing that something works. 

let sessionFactory = aConfig.BuildSessionFactory()

let aSession = sessionFactory.OpenSession()

aSession.BeginTransaction()

//AT&T is Id 100
let coID = 100

let someObj = aSession.Load(typeof<StockPrices.COMPANY>, coID) :?> StockPrices.COMPANY

printfn "Company Name: %s,  Ticker: %s" someObj.COMPANY_NAME someObj.COMPANY_TICKER

aSession.Close()

let userresp = Console.ReadLine()

The one weird piece of code is this:

let someObj = aSession.Load(typeof<StockPrices.COMPANY>, coID) :?> StockPrices.COMPANY

should return a type of  StockPrices.COMPANY, but it does not. -- it returns a generic Object.  I have not figured out why.  It certainly does in VB.

The first part:

let someObj = aSession.Load(typeof<StockPrices.COMPANY>, coID)

Anyway, I had to find a way to cast a generic Object into StockPrices.COMPANY so I could actually use it.  Browsing around the Internet I found this little puppy: ":?>"  What the devil is this?

It is know as on downcast operator the uses the syntax:

x :?> T

According to our buddies at MSFT:

"The :?> operator performs a dynamic cast, which means that the success of the cast is determined at run time. A cast that uses the :?> operator is not checked at compile time; but at run time, an attempt is made to cast to the specified type. If the object is compatible with the target type, the cast succeeds. If the object is not compatible with the target type, the runtime raises an InvalidCastException."

Anyhow, this operator allows me to cast the result into a type StockPrices.COMPANY.

I then print the output to the console.  Note:  I also get my sql query generated by NHibernate.  This is the result of setting the show_sql property to true: properties.Add("show_sql", "true").

 

Print | posted @ Sunday, June 28, 2009 10:28 AM

Comments on this entry:

Gravatar # re: Getting Stock Prices: F# & NHibernate (1)
by air max pas cher at 2/2/2012 11:30 PM


Air max 11 SUPRéMATIE pèse environ 16,3 onces, par rapport à l'air max BB4 1,5 oz pleine légers nike air max chaussure que vous pouvez trouver 1,5 oz inférieure à la demi-sac de nouilles instantanées faire, nike tn pas chere mais n'oubliez pas: vous sautez sur le terrain de la course, car une petite once 1.5, vous pouvez consommer moins sur 300J l'énergie, mais l'ensemble des termes, nike air max tn requin pour homme air max statut héréditaire air max chaussures pas de sang bien. Il ne fait aucun doute que celui-ci (en particulier les modèles noir / argent et des modèles blanc / argent) résistera à l'épreuve du temps, peut-être huit ans, peut-être 10 ans, prix air max tn Pour remédier à cette situation, Nike a acheté l'entreprise de distribution à travers le monde, afin d'obtenir plus de contr?le sur, Knight a appelé ses hommes à se concentrer sur l'Allemagne, le Mexique et le Japon super important sur le marché pour la conduite des affaires. Là, on air max tn chaussures les détaillants estiment que Nike va: commandes à l'avance pas empiler douloureuse, Je ne sais pas au début, c'est juste mon cul sur un sarcome de longue '" Knight par une blague pour enseigner aux responsables les informations, air max tn homme derniere minute nous devons réussir, mais ne peut pas perdre le sens de l'humour, et de notre culture rebelle. Pour les Etats-Unis, seuls quelques-uns peut être aussi directeur général de Knight, Nike, grace au parrainage de la ?première nuit?, occasion air max tn gratuite mais aussi un million dix qui aiment idole sportive. Nike est maintenant de 4 milliards de dollars en chiffre d'affaires des grandes entreprises, son image d'être anti-traditionnelle des menaces, un commentateur d'affaires a crié: ?Chevalier constaté que Nike devient rapidement une combinaison de l'entreprise américaine et des sports, aeroport nike air max tn requin ambivalence résultant de paratonnerre ordinaire. vous pouvez acheter, comme un ami qui souhaitent essayer cette paire de chaussures Nike nouvelle course. ?Le sport, les spectacles, la liberté libre et facile de sportivité" est la poursuite de Nike personnalisées culture d'entreprise. Chevalier collection aléatoire de certaines étoiles de l'athlétisme et l'idée d'amateurs de sports d'écrire dans l'article, on la redoute tn mais il croit la réponse la plus directe de l'entreprise est d'accro?tre.
  

Your comment:

Title:
Name:
Email:
Website:
 
Italic Underline Blockquote Hyperlink
 
 
Please add 6 and 3 and type the answer here: