Monthly Archives: December 2010

EFv4 CTP5 some missing features (mapping)

Entity Framework v4 CTP5 added some new nice features since CTP4, for example the DbSet<T>.Local property I was blogging about or Validation. But, sadly, there’s something missing, mainly due to huge refactoring.

I hit the wall with one in particular. It’s entity splitting together with TPH inheritance. If you try to map it, you’ll get Entity splitting cannot be specified for type '<entity type>' since it is part of an inheritance hierarchy.. Bummer. So one of the projects I’m working on now, is stuck in CTP4. :)

On the other hand, the good news (from reliable source ;) ) is, that in RTM this will be working fine.

Trace API support in ADO.NET provider for Firebird (FbTrace)

When I came from Firebird Conference in Bremen I was so excited about all the people being excited about Trace and Audit API :) I decided I’ll implement this in .NET provider as soon as possible. And here it is.

Right now there’s a new class (and few supporting it) on FirebirdSql.Data.Services namespace called FbTrace, that you can use to start trace session and see what’s going on on server. I’ll not describe the Trace API itself, you can find info in documentation, I’ll rather focus on how you can use it from the provider.

Right now, as I have no sharp idea how the people will use it, I implemented it simply and later, if I find some common cases, I’ll add some “shortcuts” to help with these scenarios.

If you have ever used any FbService derived class, you’ll be able to use FbTrace in under a minute.

FbTrace trace = new FbTrace();
trace.ConnectionString = "database=localhost:rrr.fdb;user=sysdba;password=masterkey";
trace.ServiceOutput += (object sender, ServiceOutputEventArgs e) =>
	{
		Console.WriteLine(e.Message);
	};
trace.DatabasesConfigurations.Add(
	new FbDatabaseTraceConfiguration()
		{
			DatabaseName = string.Empty,
			Enabled = true,
			Events = FbDatabaseTraceEvents.Connections | FbDatabaseTraceEvents.Transactions
		});
trace.Start("test");

The important stuff is in FbDatabaseTraceConfiguration class, where you specify what should be traced, exactly the same way as in fbtrace.conf (you can find this file in Firebird‘s installation). Mainly the database name to match for trace (if you want only some), whether it’s enabled (probably useful if you want to keep the configuration somewhere, but selectively turn it off and on). And finally the events you’re interested in – FbDatabaseTraceEvents enum. In the example above I’m tracing only connections and transactions (not for example stored procedures prepares or executions). All this configuration is added into DatabasesConfigurations property. You can have for sure different configurations for different databases. For Services API tracing there’s property, because it’s only one “services instance” in Firebird server, called ServiceConfiguration. At the last line I’m starting the trace session named test using method Start.

And that’s it. When something happens in the database the ServiceOutput event handler will be invoked and you’ll get the trace message.

Of course, you can also call Suspend, Stop, Resume and List methods to do accordant actions in API.

This is the initial implementation and some methods may be added (I’m already thinking about a few). Hope you enjoy it. Feel free to play with it and comment here or in list.

PAUSE command moral

Few days ago I created batch file to backup Firebird databases, Subversion repositories and some other data on a new server. During the testing of the script I put PAUSE command at the end, to see the result (or better to say errors). After I was done with polishing it up I created record in Task Scheduler and started test run. Everything finished in a couple of minutes nicely. I left it there, expecting it to do the backup during the night, as scheduled.

Next day I checked the result and the task failed with 0x8004131F aka SCHED_E_ALREADY_RUNNING. I checked CPU and disk utilization and it was clear the backup is not running. Kind of confused I ran backup manually and waited another day. And guess what, same error. As you probably now see, the problem was the PAUSE command at the end of the script. So the task was actually running, and waiting for the input. Clearly visible in Process Explorer.

I removed it and now everything works fine. Such a stupid mistake caused such a confusion. :)

DbSet<T>.Local property (EFv4, CTP5)

Currently latest CTP for Entity Framework, CTP5, contains one new property on DbSet<T>. It’s called Local and it’s very useful when you wanna work with objects you have already in memory. So it’s good for queries without hitting the database, like databinding.

You can create layer that loads objects your application needs, or you think it might need. And then you use only .Local to access that data, still full LINQ support etc. This may help to lower number of queries you’re sending to database. The property is of type ObservableCollection<T>, thus the databinding is super easy.

The method isn’t something new. In fact it’s exposing in a friendly was what’s already possible – i.e. Useful Find method on DbSet and “Local” Queries 2nd edition. It is using ObjectStateManager to find all Unchanged, Added and Modified entities, exactly the ones you’re probably interested in.

Let’s see some example:

class Program
{
	static void Main(string[] args)
	{
		/* 
		 * I have 3 rows in FOOBAR table in database.
		 */
		using (MyContext c = new MyContext())
		{
			// return's 2 rows and hits database
			var data1 = c.Set<FooBar>().OrderBy(x => x.ID).Take(2).ToArray();
			// return's 2 rows without hitting database
			var data2 = c.Set<FooBar>().Local.ToArray();
			// return's 1 row and hits database
			var data3 = c.Set<FooBar>().OrderBy(x => x.ID).Skip(2).Take(1).ToArray();
			// return's 3 rows without hitting database
			var data4 = c.Set<FooBar>().Local.ToArray();
		}
	}
}

class MyContext : DbContext
{
	public MyContext()
		: base(new FbConnection("database=localhost:rrr.fdb;user=sysdba;password=masterkey"), true)
	{ }

	protected override void OnModelCreating(System.Data.Entity.ModelConfiguration.ModelBuilder modelBuilder)
	{
		base.OnModelCreating(modelBuilder);

		modelBuilder.Entity<FooBar>().HasKey(x => x.ID);
		modelBuilder.Entity<FooBar>().Property(x => x.ID).HasColumnName("ID");
		modelBuilder.Entity<FooBar>().Property(x => x.Something).HasColumnName("S");
		modelBuilder.Entity<FooBar>().Map(m => m.ToTable("FOOBAR"));
	}
}

class FooBar
{
	public int ID { get; set; }
	public string Something { get; set; }
}

All important stuff about behavior is in comments. As you see, it acts as kind of local cache of objects, that are (mostly) reasonable to work with.

As always, nothing huge, but nice, handy.

PS: Did you noticed, I’m using Firebird? ;)