Archives for August, 2010

25
Aug

TPH mapping discriminator condition from MetadataWorkspace

The MetadataWorkspace contains a lot of useful information. Recently I was facing a challenge to get information about TPH (table per hierarchy) inheritance conditions for particular type. Sure, it’s in EDMX file and/or in MSL file. So you can parse the XML and get the info. I was on the other hand more interested getting the info from MetadataWorkspace, partially as a good “brain training” 8) side project.

Sadly the information about the mapping is very limited. Most interesting parts are not public, thus you’re forced to use reflection. So it’s a lot back and forth with, in my case, QuickWatch window. It helps a little to be familiar with MSL file structure.

static object GetNonPublicPropertyValue(this object o, string propertyName)
{
	return o.GetType()
		.GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Instance)
		.GetValue(o, null);
}

public static IEnumerable<KeyValuePair<string, object>> GetMappingConditions<T>(this ObjectContext context)
	where T : class
{
	string typeToSearch = typeof(T).Name;

	var mapping = context.MetadataWorkspace.GetItemCollection(DataSpace.CSSpace).First();

	return ((IEnumerable<object>)mapping.GetNonPublicPropertyValue("EntitySetMaps"))
		.SelectMany(entitySetMap => (IEnumerable<object>)entitySetMap.GetNonPublicPropertyValue("TypeMappings"))
		.Where(typeMapping =>
			((IEnumerable<dynamic>)typeMapping.GetNonPublicPropertyValue("IsOfTypes")).Any(type => type.Name == typeToSearch)
			||
			((IEnumerable<dynamic>)typeMapping.GetNonPublicPropertyValue("Types")).Any(type => type.Name == typeToSearch))
		.SelectMany(typeMapping => (IEnumerable<object>)typeMapping.GetNonPublicPropertyValue("MappingFragments"))
		.SelectMany(mappingFragment => (IEnumerable<object>)mappingFragment.GetNonPublicPropertyValue("AllProperties"))
		.Where(mappingFragment => mappingFragment.GetType().Name == "StorageConditionPropertyMapping")
		.Select(condition =>
			{
				bool? isNull = (bool?)condition.GetNonPublicPropertyValue("IsNull");
				string value = (string)condition.GetNonPublicPropertyValue("Value");
				return new KeyValuePair<string, object>((string)((dynamic)condition.GetNonPublicPropertyValue("ColumnProperty")).Name, (isNull.HasValue ? (object)isNull.Value : (object)value));
			});
}

Because the code is heavily using reflection and non public members, it’s possible it’ll not work other/future versions of Entity Framework. I tested it with current version, version 4.

It’s written in a compact way. If you want to further dig into partial results, I recommend to split it into foreach loops and do small steps. That’s in fact how I started and was incrementally discovering the information available at given level.

As all the data are not public, I’ll not describe how and why it is as it is. I did it using trial and error process. :) Maybe there’s other/simpler path. Feel free to use comments if you find one.

24
Aug

Vyjmenovávat sloupce v SQL příkazu nebo ne???

Nedávno se na Builderu lehce rozjela diskuze, ačkoli v threadu na odlišné téma, jestli sloupce v SQL příkazech vyjmenovávat nebo ne. Nedá mi to a přispěju taky svou troškou.

Já bych “problém” rozdělil na dvě části. První je SQL kód v aplikaci. Druhou je kód v rámci pohledů, spouští, uložených procedur atp.

V prvním případě jasně a striktně sloupce vyjmenovávám. Jednak mám pocit, že to přidá na přehlednosti. Nejenom v rámci zápisu, ale i když později človek kód prochází a třeba něco přidává – vidí co do aplikace přichází a jak se to jmenuje. Případně se tak triviálně (aka Find) dají hledat závislosti. A jednak si myslím, že to ukazuje, že člověk nad výsledkem přemýšlel. Samozřejmě platí i to klasické, že při změně struktury nedochází k neočekávanému chování, kdy aplikace tahá sloupce, o kterých nemá ponětí a nedokáže je využít.

V druhém případě to již tak striktně nemám, ačkoli stále jsem daleko od volnosti. Sloupce opět vyjmenovávám, ale mám pár – v pro mě velmi opodstatněných, triviálních případech – “povolení”, kdy nevyjmenovávám. V zásadě se jedná o případy, kdy daný objekt jen k datům něco přidává resp. je překlápí. Typicky pohled, který k sadě přidává třeba RANK. Nebo trigger kopírující data 1:1 navíc do jiné tabulky. Potom si dovolím použít * (a někdy i přesto sloupce vyjmenuji). Jinak standardně vyjmenovávám.

Kdejaký nástroj vám všechny aktuální sloupce dokáže vygenerovat: Flamerobin, SQL Server Management Studio, IBExpert, Database Workbench, … Slušně si je naformátovat do zápisu je pak triviální.

Proč psát něco, čehož chování se může změnit, aniž bych se o tom ïmplicitně dozvěděl. A samozřejmě stále platí to co jsem napsal výše o přemýšlení nad tím co píšu.

8
Aug

FbTransaction changes to support tables locking

Firebird has a feature allowing you to specify tables you want to lock (read or write and exclusive/protected/shared) when starting transaction. (Note that Firebird still uses MGA/MVCC. This is just a feature to support some scenarios.) We had constants in ADO.NET Provider for Firebird for some time, but using them resulted in wrong parameters being sent to the server and followed by exception. :)

Today I implemented support for this locking (tracker item, mailing list thread). That means sending proper sequences. The FbTransactionOptions class created earlier for timeout support was extended with new property LockTables. You can use to specify table name and lock specification. The lock specification there is in fact only subset of all options you can specify for transaction (same enumeration). You can put there whatever you want other options will be simply ignored.

Small example:

conn.BeginTransaction(new FbTransactionOptions()
	{
		TransactionBehavior = FbTransactionBehavior.ReadCommitted,  // etc.
		LockTables = new Dictionary<string, FbTransactionBehavior>
		{
			{ "TABLE_1", FbTransactionBehavior.LockWrite | FbTransactionBehavior.Shared },
			{ "TABLE_2", FbTransactionBehavior.LockWrite | FbTransactionBehavior.Exclusive }
		}
	});

Here I’m specifying that for TABLE_1 shared (huh :) ) write lock will be placed and for TABLE_2 exclusive (that sounds better, isn’t it?) write lock will be placed. Similarly you can go with LockRead.

Available right now in weekly builds and SVN.

4
Aug

Projection (select) on a collection running in parallel with exceptions handling

Few days ago I posted an extension method to run projection on a collection in parallel. The method has one problem. It’s not dealing with exceptions. And because the ordering wasn’t (and isn’t) implicitly preserved, I did this small improvement.

Right now the method returns simple structure with original item, the result (if no exception occured, sure) and exception (if any). I didn’t went to AggregateException (although you can modify the code yourself to use it). Now you can decide while consuming what to do when exception occurred. Adding some kind of cancellation shouldn’t be difficult.

The idea behind is the same as in previous version.

#region ParallelProjection
internal struct ParallelProjectionResult<TSource, TResult>
{
	public TSource Item { get; set; }
	public TResult Result { get; set; }
	public Exception Exception { get; set; }
}

internal static IEnumerable<ParallelProjectionResult<TSource, TResult>> ParallelProjection<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> projection, int maxParallelism)
{
	BlockingCollection<ParallelProjectionResult<TSource, TResult>> results = new BlockingCollection<ParallelProjectionResult<TSource, TResult>>();

	ThreadPool.QueueUserWorkItem((o) =>
	{
		Semaphore semaphore = new Semaphore(maxParallelism, maxParallelism);
		CountdownEvent countdown = new CountdownEvent(1);
		try
		{
			foreach (var item in source)
			{
				countdown.AddCount();
				semaphore.WaitOne();
				ThreadPool.QueueUserWorkItem(
					(element) =>
					{
						TSource e = (TSource)element;
						ParallelProjectionResult<TSource, TResult> result = new ParallelProjectionResult<TSource, TResult>();
						result.Item = e;
						try
						{
							result.Result = projection(e);
						}
						catch (Exception ex)
						{
							result.Exception = ex;
						}
						results.Add(result);
						semaphore.Release();
						countdown.Signal();
					},
					item);
			}
			countdown.Signal();
			countdown.Wait();
			results.CompleteAdding();
		}
		finally
		{
			if (countdown != null)
				countdown.Dispose();
			if (semaphore != null)
				semaphore.Dispose();
		}
	}, null);

	return results.GetConsumingEnumerable();
}
#endregion
4
Aug

Microsoft.Data.dll after crop

Last 24 hours was interesting. Almost everybody doing something with databases and .NET was talking about new Microsoft.Data.dll. And there has been recently a lot of clarification (i.e. this or this) (check your favorite search engine for more) what it is and what it is not and who’s target audience.

From what I read emerges that it’s focused on starting developers who may not even be interested in being “real” developers. Somebody who wants to just put some site together and run. Be close to PHP world style of working. Together with WebMatrix.

I’ll not think about whether it’s good for MS’s ecosystem or not. Although I see the the points as valid, I still don’t get it. If you’re a beginner, really beginner and you wanna create some site, would you spend some time on creating it or rather try to install i.e. WordPress. It’s probably the same challenge, but the result will be different. Not taking into account, that you would still need to have at least basic knowledge of (X)HTML, programming and databases and SQL when doing it on your own, isn’t it? OK, so maybe the novice just wants to create some site on his/her own. Learn something. Improve own skills. But all this stuff isn’t going to give him/her touch of how it’s really done. You’ll be learning something that useless for bigger, real-world, applications. Umm, than he or she may not be interested in expanding skills, really just create something for fun, you might think. But do you really think this case exists? Doesn’t it sooner or later fall into one of two categories above?

And the dynamic point of view? I read somewhere that the target audience is expected to use not so sophisticated editors etc. (BTW isn’t Visual Studio Express free???). But that’s not what bothers me. What bothers me, it’s the lack of compile-time checking (which is what I damn like when I develop). You’ll upload the site to web a you’ll have to check a lot of code (pages) to see whether it works. The refactoring is harder; ahh damn, that’s not what the target audience is going to be doing or will they? Don’t forget the find&replace is refactoring as well, and here the compile time checking is really useful?

On the other hand, maybe it’s a good idea, and only because we’re not novices and the “product” isn’t enterprise ready, we should understand it and try not to judge it with enterprise-ready eyes. Because we are maybe spinning in our own world not seeing outside the box. But I personally still think the idea how it’s done it’s wrong.

3
Aug

Let’s try something new… What about Microsoft.Data.dll?

The new Microsoft.Data.dll seems to be very “interesting”. 8-)

I generally agree, that pure raw ADO.NET is more verbose than the shown example. And that’s all. On the other hand, everybody using pure raw ADO.NET have written couple of helper methods already. And directly for his/her desired approach, with non-dynamic typing. This isn’t going to make anyones life easier. As an experiment with dynamic keyword it’s nice. But a stuff used in real world deployed application? No so sure.

Wanna go easy path? Go LINQ to SQL of Entity Framework with just 1:1 model generated from database (if we’re on MS’s stack, NHibernate or LLBLGen Pro will do the work as well). Wanna go pure SQL, all under own control? ADO.NET is waiting for you. But this, this looks like kind of mixture of both, but nothing good resulted.

By the way, will there be any support for parametrized queries? I hope so. Because if not, then it’s even more funny than it already is.
UPDATE: There’s a support: http://blog.andrewnurse.net/2010/08/03/MicrosoftDataItrsquosNotAsEvilAsYouThink.aspx.

For me it’s a step back. Or am I missing something?

2
Aug

Projection (select) on a collection running in parallel

Here’s updated version of the method.

I have here another not-general-purpose-parallel/multihtreaded-method. :) To make a long story short I needed do some transformation on collection’s elements, aka projection. Unfortunately the method I was plugging in was doing some network requests, in fact couple of requests. Sequentially, blocking processing until the response came back. I know a proper way will be to turn these requests into asynchronous, unluckily this was part of bigger architecture I could not change. I didn’t want to use AsParallel method as I expected a need for more control maybe sometime later. So I solved it abusing ThreadPool threads. Bad for scheduler and memory, as I’ll be wasting threads and resources, blocking, until reply is sent by server, but very easy for me. I told you, abusing. ;)

So I came with this method. It’s utilizing new .NET Framework 4 concurrent collections, BlockingCollection in particular as it’s great for producer-consumer scenario and I want the method to return results whenever one is done (that also implies the ordering isn’t preserved).

internal static IEnumerable<TResult> ParallelProjection<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> projection, int maxParallelism)
{
	BlockingCollection<TResult> results = new BlockingCollection<TResult>();

	ThreadPool.QueueUserWorkItem((o) =>
	{
		Semaphore semaphore = new Semaphore(maxParallelism, maxParallelism);
		CountdownEvent countdown = new CountdownEvent(1);
		try
		{
			foreach (var item in source)
			{
				countdown.AddCount();
				semaphore.WaitOne();
				ThreadPool.QueueUserWorkItem(
					(element) =>
					{
						results.Add(projection((TSource)element));
						semaphore.Release();
						countdown.Signal();
					},
					item);
			}
			countdown.Signal();
			countdown.Wait();
			results.CompleteAdding();
		}
		finally
		{
			if (countdown != null)
				countdown.Dispose();
			if (semaphore != null)
				semaphore.Dispose();
		}
	}, null);

	return results.GetConsumingEnumerable();
}

The method is straightforward, a lot of work was saved using the smart blocking collection. I’m simply reading items from the collection and applying the function to them. To not overload the system with huge number of threads I also added maxParallelism parameter. When this number of threads is processing items, I’ll stop scheduling more, using Semaphore, until some are done and again available. When there’s no item in source collection available and all item were processed I call CompleteAdding method to say I’m done and there will be no other items. Here I’m using CountdownEvent class initialized to 1 as you can’t, of course, add items if it reaches 0. Before final Wait I’m subtracting one to compensate this.

And that’s it. Again, it’s not general purpose method. Use with care, it may bring you even worse performance if wrongly used.