We like to keep things fresh here in our NuoDB Techblog, so we’re trying something new with this post. We’ve invited a developer from our community of users to contribute in a guest post, and his name is Jiri Cincura. I’m excited because he is going to talk about the great improvements he’s made to our new .NET driver. So not to steal any of his thunder I’ll leave it to you to read on – enjoy!
~Paul
I recently started working on NuoDB’s .NET driver to improve it, and especially to introduce Entity Framework support. I was playing with NuoDB before, even from .NET, but using only ODBC that was available at that time. Currently, a good basic .NET driver is available and now it even has full Entity Framework support.
When I was working on it, the main focus was to deliver the most valuable parts to developers. That means the driver currently targets .NET Framework 4.0 (or newer) and Entity Framework 4 and 5. In my opinion, that’s a majority of today’s usage.
You can expect full support for using Entity Framework with Entity Data Model as EDMX file or via Code First. No need to make decisions. Of course, the driver will also provide full LINQ support to the extent what is supported by NuoDB itself.
If you want to go further, I recommend heading to the download page and getting the latest ADO.NET driver for NuoDB and referencing it from your project. Enjoy the ride.
I’ll first create a simple application that accesses the data in NuoDB’s standard Hockey database. I’ll be using Code First, because then you can see all the code and you don’t have to fiddle with creating an EDMX file, etc.
Some basic structures:
class HockeyContext : DbContext { public HockeyContext() : base(new NuoDbConnection(Data.ConnectionString), true) { } public DbSet Hockey { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); var hockeyConf = modelBuilder.Entity(); hockeyConf.HasKey(x => x.Id); hockeyConf.Property(x => x.Id).HasColumnName("ID").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); hockeyConf.Property(x => x.Number).HasColumnName("NUMBER"); hockeyConf.Property(x => x.Name).IsRequired().HasColumnName("NAME"); hockeyConf.Property(x => x.Position).IsRequired().HasColumnName("POSITION"); hockeyConf.Property(x => x.Team).IsRequired().HasColumnName("TEAM"); hockeyConf.ToTable("HOCKEY", "USER"); } } class Hockey { public int Id { get; set; } public int Number { get; set; } public string Name { get; set; } public string Position { get; set; } public string Team { get; set; } }
I’m overriding the OnModelCreating
here to specify the mapping to the database (and even explicitly setting the information about the key, though the default convention would match it). If you’ve ever used Entity Framework and Code First this should be familiar to you.
Now some code to actually do something:
using (var ctx = new HockeyContext()) { var longestNames = ctx.Hockey.OrderByDescending(x => x.Name.Length).Select(x => x.Name).Take(3); Console.WriteLine("Top 3 longest name has:"); foreach (var item in longestNames) Console.WriteLine(item); Console.WriteLine("==="); foreach (var item in ctx.Hockey) { Console.WriteLine("{0,2}: {1,-20}\t{2}", item.Number, item.Name, item.Team); } Console.WriteLine("==="); foreach (var item in "NuoDB") { var letter = item.ToString().ToUpper(); var query = ctx.Hockey.Where(x => x.Name.ToUpper().Contains(letter)).Select(x => x.Name); Console.WriteLine(query); Console.WriteLine("Players starting with '{0}':", letter); foreach (var name in query) Console.WriteLine(name); Console.WriteLine(); } Console.WriteLine("==="); }
This code issues few queries to the database using some orderings, projections and filters. The last batch of code also prints the query being executed to the console, so you can see it and compare it with what you might write. The query looks like:
SELECT "Extent1"."NAME" AS "NAME" FROM "USER"."HOCKEY" AS "Extent1" WHERE UPPER("Extent1"."NAME") LIKE ?.p__linq__0 ESCAPE '\'
Which is more or less what I would have write myself.
We can also have a fun with updates, deletes and inserts. What about reversing all the team names?
foreach (var item in ctx.Hockey) { item.Team = new string(item.Team.Reverse().ToArray()); } var newHockey = new Hockey() { Name = "Test", Number = 10, Position = "Test", Team = "Test" }; ctx.Hockey.Add(newHockey); ctx.SaveChanges(); Console.WriteLine(newHockey.Id);
It works again as expected. No nasty surprise here. So let’s move to final step and try to dig a little bit into the infrastructure. Often you have your model and you’d like to create from it a database script (which you can then send to i.e. your DBA do review it and execute it). Note: I’m not using Entity Framework’s Migrations here, which is another way to create a database script and – more importantly – also upgrade the database(s) creating alter scripts automatically.
To see how some general data types are handled, I created this structure:
class SampleNewDatabaseContext : DbContext { public SampleNewDatabaseContext() : base(new NuoDbConnection(Data.ConnectionString), true) { } public DbSet SomeEntities { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity().ToTable("TEST_TABLE", "USER"); } } class SomeEntity { public long Id { get; set; } public Guid Guid { get; set; } public string S { get; set; } public double D { get; set; } }
Maybe you know, NuoDB currently does not have native support for GUID data type, but I did some extra work so you can save and read this basic data type without any hassle. If you run this code:
using (var ctx = new SampleNewDatabaseContext()) { Console.WriteLine(((IObjectContextAdapter)ctx).ObjectContext.CreateDatabaseScript()); }
You’ll get back the script:
CREATE TABLE "USER"."TEST_TABLE" ( "Id" BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, "Guid" CHAR(38) NOT NULL, "S" CLOB, "D" DOUBLE PRECISION NOT NULL ); ALTER TABLE "USER"."TEST_TABLE" ADD PRIMARY KEY ("Id");
Of course, if you provided some more mapping details in OnModelCreating
the script would be different, so you might for instance add some length limit to the “S
” property so it ends up being “varchar(x)
” for example.
I hope you enjoyed this quick overview of NuoDB’s Entity Framework support and grab my code snippets and play with them.