Is there a way to use SqlSpatialFunctions without Linq to Entities? - c#

From System.Data.Entity.SqlServer.SqlSpatialFunctions class definition:
Contains function stubs that expose SqlServer methods in Linq to Entities.
I know that Linq to Entities is mentioned specifically, however I was wondering if some functionality can be replicated in my back end code.
I've got an account Model, with lazy loaded collection of Polygons. Each Polygon contains a DbGeography type property called Location.
I'm trying to get all Polygons that interesct certain point (which also has lazy loaded property Address, which has DbGeography type property called Location).
I can do it like this:
var matchedPolygons =
account.Polygons.Where(
x =>
point.Address.Location.Intersects(x.Polygon.Location)).ToList();
which works fine.
In order to try to improve the performance, I thought it would be a good idea to slightly reduce the Polygon data.
var matchedPolygons =
account.Polygons.Where(
x =>
point.Address.Location.Intersects(SqlSpatialFunctions.Reduce(x.Polygon.Location, 100))).ToList();
This however throws the following System.NotSupportedException exception:
This function can only be invoked from LINQ to Entities.
I know I can retrieve the polygons directly from my repository layer using the Reduce method above, but since I'm using lazy loading and have Polygons collection available to me already, I thought there might be a way of using SqlSpatialFunctions at this stage.

The only thing I've ever been able to come up with a gross hack. It works, but I make no claim as to elegance.
Toss in these includes (make the references as well):
using System.Data.Entity.Spatial;
using System.Data.SqlTypes;
Convert the DbGeography to a SqlGeography:
Microsoft.SqlServer.Types.SqlGeography sqlGeography = Microsoft.SqlServer.Types.SqlGeography.STGeomFromWKB(new SqlBytes(geog.AsBinary()), mydbgeog.CoordinateSystemId);
Maybe it's okay if you keep it as SqlGeography, but if not convert it back.
sqlGeography = sqlGeography.Reduce(50);
mydbgeog = DbGeography.FromBinary(sqlGeography.STAsBinary().Value);
It's the fastest way I know of to toss back and forth between DbGeography and SqlGeography. Again, it's gross and requires an additional library to be in place but honestly there's a lot of stuff in SqlGeography that for a big GIS application will probably need.

Related

Intersect two layers and get resulting features

I have X layers on a map and I need to intersect chosen layers (two per time) and color resulting features.
I'm trying to get this code working
// get first feature (index 0)
ESRI.ArcGIS.ADF.Web.Geometry.Geometry adfFeature =
m_firstLayer.GeometryFromRow(m_firstLayer.Rows[0])
as ESRI.ArcGIS.ADF.Web.Geometry.Geometry;
// THE FOLLOWING LINE RETURNS NULL
ESRI.ArcGIS.Geometry.IGeometry featureInterface =
adfFeature as ESRI.ArcGIS.Geometry.IGeometry;
ESRI.ArcGIS.Geometry.ITopologicalOperator topoOp =
adfFeature as ESRI.ArcGIS.Geometry.ITopologicalOperator;
How to use the IGeometry interface with an ADF Geometry object?
I can't really find samples to intersect features between two layers, and it's a pity that Spatial Joins are just a arcgis desktop function, I surely could use them!
I do not think you use the IGeometry directly. However if you know the specialized type (Point, Polyline, Polygon) you can convert (see the "Web ADF to ArcGIS Server ArcObjects" bullets) to ArcObjects.
You could test what subtype your ESRI.ArcGIS.ADF.Web.Geometry.Geometry adfFeature is and do conversion accordingly.
By the way I suggest that you never use the "as" cast since it can fail silently (just returning null). Instead I suggest:
ESRI.ArcGIS.Geometry.IGeometry featureInterface =
(ESRI.ArcGIS.Geometry.IGeometry)adfFeature;
Then you will see the problem as soon as it occurs.

NHibernate lazy loading doesn't appear to be working for my domain?

I'm new to NHibernate, but have managed to get it all running fine for my latest project. But now I've reached the inevitable performance problem where I need to get beyond the abstraction to fix it.
I've created a nunit test to isolate the method that takes a long time. But first a quick overview of my domain model is probably a good idea:
I have a 'PmqccForm' which is an object that has a 'Project' object, which contains Name, Number etc and it also has a 'Questions' object, which is a class that itself contains properties for various different 'Question' objects. There is a JobVelocityQuestion object which itself has an answer and some other properties, and a whole bunch of similar Question objects.
This is what I'm talking about with my PmqccForm having a Questions object
This is the questions part of the model:
The key point is that I want to be able to type
form.Questions.JobVelocityQuestion
as there is always exactly 1 JobVelocityQuestion for each PmqccForm, its the same for all the other questions. These are C# properties on the Questions object which is just a holding place for them.
Now, the method that is causing me issues is this:
public IEnumerable<PmqccForm> GetPmqccFormsByUser(StaffMember staffMember)
{
ISession session = NHibernateSessionManager.Instance.GetSession();
ICriteria criteria = session.CreateCriteria(typeof(PmqccForm));
criteria.CreateAlias("Project", "Project");
criteria.Add(Expression.Eq("Project.ProjectLeader", staffMember));
criteria.Add(Expression.Eq("Project.IsArchived", false));
return criteria.List<PmqccForm>();
}
A look in my console from the Nunit test which just runs this method shows that there is nearly 2000 sql queries being processsed!
http://rodhowarth.com/otherstorage/queries.txt is the console log.
The thing is, at this stage I just want the form object, the actual questions can be accessed on a need to know basis. I thought that NHibernate was meant to be able to do this?
Here is my mapping file:
http://rodhowarth.com/otherstorage/hibernatemapping.txt
Can anyone hint me as to what I'm missing? or a way to optimize what I'm doing in relation to NHibernate?
What if I made the questions a collection, and then made the properties loop through this collection and return the correct one. Would this be better optimization from nhibernates point of view?
Just try to add fetch="subselect" to the mapping file for Questions component and see if this solves the issue with multiple selects to that table - you should now see one 2nd select instead of hundreds separate queries, e.g.
<component name="Questions" insert="true" update="true" class="PmqccDomain.DomainObjects.Questions" fetch="subselect">
See for more info - Improving performance

How to Convert ILayer to IPolygon In ArcObjects

Having trouble converting an Ilayer to an IPolygon.
I am developing a toolbar for ArcMap and I grab a layer via code from the side table of contents. The Layer is a Polygon, but the code won't convert it to a IPolygon.
Can anyone help me out? This is the code I am using to try and convert it to a IPolygon...
IPolygon poly = m_document.Maps.get_Item(0).get_Layer(0) as IPolygon;
I can do this:
ILayer layer = m_document.Maps.get_Item(0).get_Layer(0) as ILayer;
And that works, just not converting it to a IPloygon..
If you want to access the geometries contained in a shapefile layer, you have to get the layer's feature class. This is a property of the IFeatureLayer interface, so you'll have to cast your layer (which is an ILayer) first:
IFeatureLayer FLayer = layer as IFeatureLayer;
IFeatureClass FClass = FLayer.FeatureClass;
If you have a feature class, you can get features by index (slow) or by defining a cursor on the feature class (this is fast and the preferred way when you want to handle lots of features. Search for IFeatureCursor; ESRI docs usualy come with good code snippets).
If your feature class contains only one feature, or if you only want one feature, You can use the GetFeature method:
IFeature MyFeature = FClass.GetFeature(0);
Now you're almost there. A feature's geometry is tucked away in its Shape property:
IPolygon MyPoly = MyFeature.Shape as IPolygon;
The extra cast is needed because the Shape property is an IPolygon, which is a more specific IGeometry.
The ILayer will be made up of multiple polygons. Think of a layer as a sql table and a feature as a row in that table. The IPolygon will refer to the geometry that makes up an individual feature. You may need to cast that ILayer as something like an IFeatureLayer to get access to the right properties/methods to access the individual features within your layer.

LINQ-like or SQL-like DSL for end-users to run queries to select (not modify) data?

For a utility I'm working on, the client would like to be able to generate graphic reports on the data that has been collected. I can already generate a couple canned graphs (using ZedGraph, which is a very nice library); however, the utility would be much more flexible if the graphs were more programmable or configurable by the end-user.
TLDR version
I want users to be able to use something like SQL to safely extract and select data from a List of objects that I provide and can describe. What free tools or libraries will help me accomplish this?
Full version
I've given thought to using IronPython, IronRuby, and LuaInterface, but frankly they're all a bit overpowered for what I want to do. My classes are fairly simple, along the lines of:
class Person:
string Name;
int HeightInCm;
DateTime BirthDate;
Weight[] WeighIns;
class Weight:
int WeightInKg;
DateTime Date;
Person Owner;
(exact classes have been changed to protect the innocent).
To come up with the data for the graph, the user will choose whether it's a bar graph, scatter plot, etc., and then to actually obtain the data, I would like to obtain some kind of List from the user simply entering something SQL-ish along the lines of
SELECT Name, AVG(WeighIns) FROM People
SELECT WeightInKg, Owner.HeightInCm FROM Weights
And as a bonus, it would be nice if you could actually do operations as well:
SELECT WeightInKg, (Date - Owner.BirthDate) AS Age FROM Weights
The DSL doesn't have to be compliant SQL in any way; it doesn't even have to resemble SQL, but I can't think of a more efficient descriptive language for the task.
I'm fine filling in blanks; I don't expect a library to do everything for me. What I would expect to exist (but haven't been able to find in any way, shape, or form) is something like Fluent NHibernate (which I am already using in the project) where I can declare a mapping, something like
var personRequest = Request<Person>();
personRequest.Item("Name", (p => p.Name));
personRequest.Item("HeightInCm", (p => p.HeightInCm));
personRequest.Item("HeightInInches", (p => p.HeightInCm * CM_TO_INCHES));
// ...
var weightRequest = Request<Weight>();
weightRequest.Item("Owner", (w => w.Owner), personRequest); // Indicate a chain to personRequest
// ...
var people = Table<Person>("People", GetPeopleFromDatabase());
var weights = Table<Weight>("Weights", GetWeightsFromDatabase());
// ...
TryRunQuery(userInputQuery);
LINQ is so close to what I want to do, but AFAIK there's no way to sandbox it. I don't want to expose any unnecessary functionality to the end user; meaning I don't want the user to be able to send in and process:
from p in people select (p => { System.IO.File.Delete("C:\\something\\important"); return p.Name })
So does anyone know of any free .NET libraries that allow something like what I've described above? Or is there some way to sandbox LINQ? cs-script is close too, but it doesn't seem to offer sandboxing yet either. I'd be hesitant to expose the NHibernate interface either, as the user should have a read-only view of the data at this point in the usage.
I'm using C# 3.5, and pure .NET solutions would be preferred.
The bottom line is that I'm really trying to avoid writing my own parser for a subset of SQL that would only apply to this single project.
There is a way to sandbox LINQ or even C#: A sandboxed appdomain. I would recommend you look into accepting and compiling LINQ in a locked-down domain.
Regarding NHibernate, perhaps you can pass the objects into the domain without exposing NHibernate at all (I don't know how NHibernate works). If this is not possible, perhaps the connection to the database used within the sandbox can be logged in as a user who is granted only SELECT permissions.
Maybe the expressions will come handy for You.
You could provide simple entry places for:
a) what to select - user is expected to enter an expression only _ probably member and arithmetic expressions - those are subclasses of the expression class
b) how to filter the things = again only expressions are expected
c) ordering
d) joining?
Expressions don't let You do File.Delete because You operate only on precise domain objects (which probably don't have this functionality). The only thing You have to check is whether the parameters of the said expressions are of Your domain types. and Return types of said expressions are of domain types (or generic types in case of IEnumerable<> or IQuerable<>
this might prove helpful
I.E. expressions don't let You write multi-line statements.
Then You build your method chain in code
and voila.
There comes the data
I ended up using a little bit of a different approach. Instead of letting users pick arbitrary fields and make arbitrary graphs, I'm still presenting canned graphs, but I'm using Flee to let the user filter out exactly what data is used in the source of the graph. This works out nicely, because I ended up making a set of mappings from variable names to "accessors", and then using those mappings to inject variables into the user-entered filters. It ended up something like:
List<Mapping<Person>> mappings;
// ...
mappings.Add(new Mapping("Weight", p => p.Weight, "The person's weight (in pounds)"));
// ...
foreach (var m in mappings)
{
context.Variables[m.Name] = m.Accessor(p);
}
// ...
And you can even give an expression context an "owner" (think Ruby's instance_eval, where the context is executed with score of the specified object as this); then the user can even enter a filter like Weight > InputNum("The minimum weight to see"), and then they will be prompted thusly when the filter is executed, because I've defined a method InputNum in the owning class.
I feel like it was a good balance between effort involved and end result. I would recommend Flee to anyone who has a need to parse simple statements, especially if you need to extend those statements with your own variables and functions as well.

Common problem for me in C#, is my solution good, stupid, reasonable? (Advanced Beginner)

Ok, understand that I come from Cold Fusion so I tend to think of things in a CF sort of way, and C# and CF are as different as can be in general approach.
So the problem is: I want to pull a "table" (thats how I think of it) of data from a SQL database via LINQ and then I want to do some computations on it in memory. This "table" contains 6 or 7 values of a couple different types.
Right now, my solution is that I do the LINQ query using a Generic List of a custom Type. So my example is the RelevanceTable. I pull some data out that I want to do some evaluation of the data, which first start with .Contains. It appears that .Contains wants to act on the whole list or nothing. So I can use it if I have List<string>, but if I have List<ReferenceTableEntry> where ReferenceTableEntry is my custom type, I would need to override the IEquatable and tell the compiler what exactly "Equals" means.
While this doesn't seem unreasonable, it does seem like a long way to go for a simple problem so I have this sneaking suspicion that my approach is flawed from the get go.
If I want to use LINQ and .Contains, is overriding the Interface the only way? It seems like if there way just a way to say which field to operate on. Is there another collection type besides LIST that maybe has this ability. I have started using List a lot for this and while I have looked and looked, a see some other but not necessarily superior approaches.
I'm not looking for some fine point of performance or compactness or readability, just wondering if I am using a Phillips head screwdriver in a Hex screw. If my approach is a "decent" one, but not the best of course I'd like to know a better, but just knowing that its in the ballpark would give me little "Yeah! I'm not stupid!" and I would finish at least what I am doing completely before switch to another method.
Hope I explained that well enough. Thanks for you help.
What exactly is it you want to do with the table? It isn't clear. However, the standard LINQ (-to-Objects) methods will be available on any typed collection (including List<T>), allowing any range of Where, First, Any, All, etc.
So: what is you are trying to do? If you had the table, what value(s) do you want?
As a guess (based on the Contains stuff) - do you just want:
bool x= table.Any(x=>x.Foo == foo); // or someObj.Foo
?
There are overloads for some of the methods in the List class that takes a delegate (optionally in the form of a lambda expression), that you can use to specify what field to look for.
For example, to look for the item where the Id property is 42:
ReferenceTableEntry found = theList.Find(r => r.Id == 42);
The found variable will have a reference to the first item that matches, or null if no item matched.
There are also some LINQ extensions that takes a delegate or an expression. This will do the same as the Find method:
ReferenceTableEntry found = theList.FirstOrDefault(r => r.Id == 42);
Ok, so if I'm reading this correctly you want to use the contains method. When using this with collections of objects (such as ReferenceTableEntry) you need to be careful because what you're saying is you're checking to see if the collection contains an object that IS the same as the object you're comparing against.
If you use the .Find() or .FindAll() method you can specify the criteria that you want to match on using an anonymous method.
So for example if you want to find all ReferenceTableEntry records in your list that have an Id greater than 1 you could do something like this
List<ReferenceTableEntry> listToSearch = //populate list here
var matches = listToSearch.FindAll(x => x.Id > 1);
matches will be a list of ReferenceTableEntry records that have an ID greater than 1.
having said all that, it's not completely clear that this is what you're trying to do.
Here is the LINQ query involved that creates the object I am talking about, and the problem line is:
.Where (searchWord => queryTerms.Contains(searchWord.Word))
List<queryTerm> queryTerms = MakeQueryTermList();
public static List<RelevanceTableEntry> CreateRelevanceTable(List<queryTerm> queryTerms)
{
SearchDataContext myContext = new SearchDataContext();
var productRelevance = (from pwords in myContext.SearchWordOccuranceProducts
where (myContext.SearchUniqueWords
.Where (searchWord => queryTerms.Contains(searchWord.Word))
.Select (searchWord => searchWord.Id)).Contains(pwords.WordId)
orderby pwords.WordId
select new {pwords.WordId, pwords.Weight, pwords.Position, pwords.ProductId});
}
This query returns a list of WordId's that match the submitted search string (when it was List and it was just the word, that works fine, because as an answerer mentioned before, they were the same type of objects). My custom type here is queryTerms, a List that contains WordId, ProductId, Position, and Weight. From there I go about calculating the relevance by doing various operations on the created object. Sum "Weight" by product, use position matches to bump up Weights, etc. My point for keeping this separate was that the rules for doing those operations will change, but the basic factors involved will not. I would have even rather it be MORE separate (I'm still learning, I don't want to get fancy) but the rules for local and interpreted LINQ queries seems to trip me up when I do.
Since CF has supported queries of queries forever, that's how I tend to lean. Pull the data you need from the db, then do your operations (which includes queries with Aggregate functions) on the in-memory table.
I hope that makes it more clear.

Categories

Resources