System.Linq.Dynamic and Spatial Searches

On my current project i am doing a LOT of dynamic searches.

Lot’s of them go through System.Linq.Dynamic library - it is really just one .cs file. As library has lost somewhere on internet, the only place i have managed to find it is on one of github’s repository :

I had to run some spatial searches over exposed DbGeography type - those are directly on database - via Entity Framework

public class Town { public string Name { get; set; } 
public DbGeography Location { get; set; } } 

The problem is, dynamic queries (based on string) simply won’t work on that.

_db.Towns.Where("Location.Distance(@0) < 20000", someLocation).ToList() 

Such query will bruttaly fail with “Methods on type ‘DbGeography’ are not accessible”. Going through the code shows us:

if (!IsPredefinedType(method.DeclaringType))

is throwing exception. Solution for that is simple and requires to add DbGeography to ‘predefinedTypes’ variable. Now, following test will pass:

[Fact]
public void DistanceSearchShouldWork()
{
	var warsaw = new Town() { Name = "Warsaw", Location = DbGeography.FromText("POINT(52.229718 21.012214)") };
	var lodz = new Town() { Name = "Lodz", Location = DbGeography.FromText("POINT(51.759304 19.455969)") };
	var berlin = new Town() { Name = "Berlin", Location = DbGeography.FromText("POINT(52.523206 13.410836)") };
	var towns = new List
			    {
				    warsaw,
				    lodz,
				    berlin
			    }.AsQueryable();

	var distance = warsaw.Location.Distance(lodz.Location);

	Assert.Equal(1, towns.Where("Location.Distance(@0) < 20000", warsaw.Location).Count());
	Assert.Equal(2, towns.Where("Location.Distance(@0) < 200000", warsaw.Location).Count());
	Assert.Equal(3, towns.Where("Location.Distance(@0) < 2000000", warsaw.Location).Count());
}

In case you would like to grap solution directly - you can do that on fork here.

comments powered by Disqus