Monthly Archives: February 2010

Complex types and stored procedures – 2nd edition

Some time ago I was writing about not supported scenario when you have entity with complex type and you want to map result of stored procedure to this entity. I couldn’t believe that this, from my point of view fairly common, scenario will not be supported in designer in RTM.

Right now I’m running RC of Visual Studio 2010 (the development probably in feature freeze mode) and the limitation is still there. :( Jeff Derstadt was absolutely right, unfortunately. Although Zeeshan Hirani in forum said, he was able to do it manually, it’s uncomfortable. Same as complex types in EFv1.

Looks like complex types, sadly, are still not first class citizens for designer.

Spatial data and Entity Framework – from real world usage

Julie Lerman created a post about spatial data usage in Entity Framework. Her conclusions are correct. But because from last three projects I did on Entity Framework two of them are working with spatial data (every customer wants a Google Maps or Bing Maps on website, it’s like cup holders in cars) I would like share my solution as well some ideas behind why I used this approach.

First and foremost Entity Framework doesn’t support spatial data now. So you have to create some workaround. The idea getting the data through blob is exactly what I created. In my tables where I need to save some coordinates (it’s mainly a point) I create simple column with this data type – I consider this clean initial work better, because maybe sometimes/somewhere/somebody will work with this structures so to have it clean. Then for the workaround I add XXX_bin column where I’ll store the binary representation of spatial data and use it for Entity Framework. Something like this:

[Location] geography Default geography::STGeomFromText('POINT EMPTY', 4326) NOT NULL,
[Location_bin] Varbinary(max) NOT NULL,

Because I’m working only through Entity Framework I need to update the Location automatically as there might be (and are) indices or other stuff working with it. To make it transparent I’m using insert or update trigger:

if (update(Location_bin))
begin
  update %tablename% set
    Location = geography::STGeomFromWKB(Location_bin, 4326)
  where
     ID in (select ID from inserted);
end

If you expect somebody updating the Location column directly too, you need to create another trigger and make sure you’ll not end up in infinite loop.

To support the – in my case – points for UI developers I create in every entity computed property turning Location_bin into my LatLong struct. This struct is using Microsoft.SqlServer.Types namespace.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Types;

namespace FooBar
{
    public struct LatLong
    {
        public double Lat { get; set; }
        public double Long { get; set; }

      public static LatLong FromSqlBytes(byte[] bytes)
      {
        SqlGeography g = SqlGeography.STGeomFromWKB(new SqlBytes(bytes), 4326);
        return new LatLong { Lat = g.Lat.Value, Long = g.Long.Value };
      }
  
      public byte[] ToSqlBytes()
      {
        return SqlGeography.Point(this.Lat, this.Long, 4326).STAsBinary().Buffer;
      }
    }
}
public LatLong Location
{
  get
  {
    return LatLong.FromSqlBytes(this.Location_bin);
  }
  set
  {
    this.Location_bin = value.ToSqlBytes();
  }
}

This creates almost seamless support for other developers when using spatial data in Entity Framework – inserting, updating, deleting all works without notice from others (if you’re not looking into internal implementation).

There are only two problems, both solvable.

First one is that developer cannot filter/sort/… using Location property. This isn’t probably a big problem. As (s)he doesn’t have spatial methods (like i.e. Distance) available, so the queries will not make sense. Which brings me to the other problem and that’s the querying. With EFv1 I created stored procedures for these queries and returned data through these. Same works for EFv4. If you have strict set of results you need, this is probably easiest solution. The other one, working in EFv4 is LINQ function imports via EdmFunction attribute. For computations I’m going to use I create function in T-SQL doing the work and I import it into my solution thru above noted attribute. The simple Distance method may look like:

create function Distance
(
  @Location_bin1 varbinary(max),
  @Location_bin2 varbinary(max)
)
returns int
as
begin
  return geography::STGeomFromWKB(@Location_bin1, 4326).STDistance(geography::STGeomFromWKB(@Location_bin2, 4326));
end

And

[EdmFunction("model.Store", "Distance")]
internal static int Distance(this byte[] location1, byte[] location2)
{
  throw new NotSupportedException();
}

Sure, when calling this function for a big resultsets it may be a performance bottleneck (I recommend doing there as much work as possible, even at the price of more functions doing similar stuff, to not create a deep function calls.), but with additional filters it works well.

protected IQueryable<Something> SomethingInDistance(LatLong point, int distance)
{
  byte[] spatialData = point.ToSqlBytes();
  return this.Somethings.Where(o => o.Location_bin.Distance(spatialData) < distance);
}

Another way could be to create a view (if you know the parameters in advance) and do explicit join (table/entityset <> view/entityset) in EF. Or do the filtering on client (if reasonably small). And I’m sure I’ll find other ways how to get the data you want back, simply choose what fits your needs best.

Although it may look like a lot of work, it isn’t. In fact you’re pretty fast (there’s a high level of reusability) if you know what to do (and after one implementation you will).

Managing TortoiseSVN commit and update from command line and creating PowerShell alias

I started to using PowerShell in my development environment simply to learn it a little bit more (though I’m still using the old command from cmd or UNIX) and also to get out of the stone aged cmd. And because I’m using the console a lot – yep, I get used to it on UNIX/Linux machines with terminal access) I was not happy to open explorer just to issue commit or update to/from SVN (these are most common commands I’m using, together with diff in commit window).

And happily TortoiseSVN has a utility to manage most of the basic tasks. It’s called TortoiseProc. To do commit or update in current directory, you’ll simply execute:

tortoiseproc /command:commit /path:.

or

tortoiseproc /command:update /path:.

For a while I was happy with it. But typing it everytime or looking into history (I wish cmd/PS had Ctrl+R as bash has) was not perfect for me. So I started looking for a way to create alias in PowerShell. Some kind of alias. PowerShell, sure, has something like this, I thought. And it has – Set-Alias. Though, limited. If you try to create alias to command with hardcoded parameters, …

set-alias commit "tortoiseproc /command:commit /path:."

… as I was trying, you’ll not succeed. After some searching and trying I found and an idea from Andrew Watt using a function (yes, I’m a PowerShell newbie). It’s easy and convenient to wrap the command into it.

So finally I create PowerShell aliases for TortoiseSVN to nicely support my work from command line:

set-alias update fn_update
set-alias commit fn_commit
function fn_update {tortoiseproc /command:update /path:.}
function fn_commit {tortoiseproc /command:commit /path:.} 

SQL command when inserting M:N association with identity columns in the underlying table

Today I uncovered a magic command from Entity Framework v4 when you create M:N association and the underlying table is defined with both columns as identity and you insert there. I don’t what’s it good for, as this table in fact only stores the two IDs to connect other tables. But somebody may build some logic on identity there, sure.

When I first saw the command, I was completely stunned. I had no idea what’s going on there and whether I see there one or more commands. You can have fun too:

declare @generated_keys table([ID_A] int, [ID_B] int)
insert [dbo].[A_B]
output inserted.[ID_A], inserted.[ID_B] into @generated_keys
default values
select t.[ID_A], t.[ID_B]
from @generated_keys as g join [dbo].[A_B] as t on g.[ID_A] = t.[ID_A] and g.[ID_B] = t.[ID_B]
where @@ROWCOUNT > 0

As an old school guy I was first looking for semicolons and then later tried to decode it by “parsing” the content.

Isn’t it nice… :)

EdmGen2 with EFv4

EdmGen2 is a nice tool. Especially if you know EdmGen you may find it useful. I.e. you may speed up the start of you application by pregenerating views directly from EDMX file.

Unfortunately if you try to use it with EFv4 it will crash. But we have sources, why not to fix the problem? And that’s what I did.

First problem was with new namespaces the EFv4 EDMX file has. The new ones are:

static string csdlNamespace = "http://schemas.microsoft.com/ado/2008/09/edm";
static string ssdlNamespace = "http://schemas.microsoft.com/ado/2009/02/edm/ssdl";
static string mslNamespace = "http://schemas.microsoft.com/ado/2008/09/mapping/cs";

The next step is to switch the project to target .NET Framework 4, you can do it in project options. And finally check whether the references, especially System.Data.Entity.Design, where the interesting objects are, are pointing to “4.0.0.0 versions” and correct if needed.

Done. Build and use. And if you want to have it without work, grab this file with all changes already done ;) .

New Windows Mobile 7 – why people see so much “problems”?

There’s a lot of rumors about the new Windows Mobile 7, especially in last days before MWC. A lot of unconfirmed information is flying around and lot of comments. What I would like to focus on is backward compatibility, Marketplace, Compact Framework and new look and feel of homescreen.

A lot of folks is not happy about dropping backward compatibility. I, on the other hand, am pleased with this step. The world has changed, especially the mobile world. What was ok in 2001, is not in 2010. I like new trends in control, give me that on WM too.

Marketplace should be only way to get application into device. For me as a developer this is little scary, because even for simple free utility you’ll need to buy certificate for developer. But if the applications will be thoroughly tested, I’m ok with it. And may increase the quality of apps as well.

Backward compatibility for Compact Framework is interesting too. The idea of writing application in current century’s tool like C# and .NET with GC and nice libraries I like. But JITing on not so much powerful devices? I don’t know. Here I like the speed and responsiveness of app. What MonoTouch is doing is IMO the way. And if MS would provide such a tool … neat!

I don’t know whether the screenshots and descriptions I saw/read are close to the reality or not (we’ll see in couple of days), but it looks like, there’s no classic home screen as I use it now (with Spb Diary) (and how some screens show the new iPhone OS will have it) – tasks, appointments for next couple of days/weeks. This means a lot of people will be pissed off, because the device is also work and productivity tool. Will it degrade it to into “just” device for fun, while iPhone will be slowly trying to get the attention of people using the phone for work half of the day too?