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.