24
Jun

Client-side properties and any remote LINQ provider

David Fowler on the ASP.NET team and I have been bouncing ideas about on how to solve an annoyance using LINQ:

If you write properties on the client you can’t use them in remote LINQ operations.

The problem occurs because these properties can’t be translated and sent to the server as they have been compiled into intermediate language (IL) and not LINQ expression trees that are required for translation by IQueryable implementations. There is nothing available in .NET to let us reverse-engineer the IL back into the methods and syntax that would allow us to translate the intended operation into a remote query.

This means you end up having to write your query in two parts; firstly the part the server can do, a ToList or AsEnumerable call to force that to happen and bring the intermediate results down to the client, and then the operations that can only be evaluated locally. This can hurt performance if you want to reduce or transform the result set significantly.

What we came up (David, Colin Meek and myself) is a provider-independent way of declaring properties just once so they can be used in both scenarios. Computed properties for LINQ to SQL, LINQ to Entities and anything else LINQ enabled with little effort and it works great on .NET 3.5 SP1 :)

Before example

Here we have extended the Employee class to add Age and FullName. We only wanted to people with “da” in their name but we are forced to pull down everything to the client in order to the do the selection.

partial class Employee {
	public string FullName {
		get { return Forename + " " + Surname; }
	}

	public int Age {
		get { return DateTime.Now.Year - BirthDate.Year -
			(DateTime.Now.Month < BirthDate.Now.Month
			|| DateTime.Now.Month == BirthDate.Now.Month && DateTime.Now.Day < BirthDate.Now.Day) ? 1 : 0);
		}
	}
}...var employees = db.Employees.ToList().Where(e => e.FullName.Contains("da")).GroupBy(e => e.Age);

After example

Here using our approach it all happens server side… and works on both LINQ to Entities and LINQ to SQL.

partial class Employee {
    private static readonly CompiledExpression<Employee,string> fullNameExpression =       DefaultTranslationOf<Employee>.Property(e => e.FullName).Is(e => e.Forename + " " + e.Surname);
    private static readonly CompiledExpression<Employee,int> ageExpression =       DefaultTranslationOf<Employee>.Property(e => e.Age).Is(e => DateTime.Now.Year - e.BirthDate.Value.Year - ((DateTime.Now.Month < e.BirthDate.Value.Month || (DateTime.Now.Month == e.BirthDate.Value.Month && DateTime.Now.Day < e.BirthDate.Value.Day)) ? 1 : 0)));

    public string FullName {
        get { return fullNameExpression.Evaluate(this); }
    }

    public int Age {
        get { return ageExpression.Evaluate(this); }
    }
}...

var employees = db.Employees.Where(e => e.FullName.Contains("da")).GroupBy(e => e.Age).WithTranslations();

Getting started

Check out this download which includes the necessary project to drop-in to your solution. The caveat to the usage technique shown above is you need to ensure your class has been initialized before you write queries to it. If this is a problem check out the usage considerations section below.

The other major caveat is obviously the expression you register for a property must be able to be translated to the remote store so you will need to constrain yourself to the methods and operators your IQueryable provider supports.

Usage considerations

There are a few alternative ways to use this rather than the specific examples above.

Registering the expressions

You can register the properties in the class itself as shown in the examples which means the properties themselves can evaluate the expressions without any reflection calls. Alternatively if performance is less critical you can register them elsewhere and have the methods look up their values dynamically via reflection. e.g.

…
DefaultTranslationOf<Employee>.Property(e => e.FullName).Is(e => e.Forename + " " + e.Surname);
var employees = db.Employees.Where(e => e.FullName.Contains("da")).GroupBy(e => e.Age).WithTranslations();
…
partial class Employee {
    public string FullName { get { return DefaultTranslationOf<Employees>.Evaluate<string>(this, MethodInfo.GetCurrentMethod());} }
}

If performance of the client-side properties is critical then you can always have them as regular get properties with the full code in there at the expense of having the calculation duplicated, once in IL in the property and once as an expression for the translation.

Different maps for different scenarios

Sometimes certain parts of your application may want to run with different translations for different scenarios, performance etc. No problem!

The WithTranslations method normally operates against the default translation map (accessed with DefaultTranslationOf) but there is also another overload that takes a TranslationMap you can build for specific scenarios, e.g.

var myTranslationMap = new TranslationMap();
myTranslationMap.Add<Employees, string>(e => e.Name, e => e.FirstName + " " + e.LastName);
var results = (from e in db.Employees where e.Name.Contains("martin") select e).WithTranslations(myTranslationMap).ToList();

Not specifying WithTranslation everywhere

If you are happy to always have the default translation applied simply add the following statement to the top of your file which will bring in a bunch of extensions methods for the usual LINQ query operators that already apply WithTranslation for you :)

using Microsoft.Linq.Translations.Auto;

With .NET 4.0

You should be able to drop the ExpressionVisitor class in the download and reference the built-in one.

How it works

CompiledExpression<T, TResult>

The first thing we needed to do was get the user-written client-side “computed” properties out of IL and back into expression trees so we could translate them. Given that we also want to evaluate them on the client we need to compile them at run time so CompiledExpression exists which just takes an expression of Func<T, TResult>, compiles it and allows evaluation of objects against the compiled version.

ExpressiveExtensions

This little class provides both the WithTranslations extensions methods and the internal TranslatingVisitor that unravels the property accesses into their actual registered Func<T, TResult> expressions via the TranslationMap so that the underlying LINQ provider can deal with that instead.

TranslationMap

We need to have a map of properties to compiled expressions and for that purpose TranslationMap exists. You can create a TranslationMap by hand and pass it in to WithTranslations if you want to programmatically create them at runtime or have different ones for different scenarios but generally you will want to use…

DefaultTranslationOf

This helper class lets you register properties against the default TranslationMap we use when nothing is passed to WithTranslations. It also allows you to lookup what is already registered so you can evaluate to that although there is a small reflection performance penalty for that:

public int Age { get { return DefaultTranslationOf<Employees>.Evaluate<int>(this, MethodInfo.GetCurrentMethod()); } }

AutoTranslation

Remembering to specify WithTranslations everywhere can be a pain so if you always want to go via translation and use the default TranslationMap you can include the Microsoft.Linq.Translations.Auto namespace in your code which includes extension methods for all the regular LINQ operations that saves you having to remember.

Have fun!

[)amien

04
Jun

LINQ to SQL resources

A quick round-up of some useful LINQ to SQL related resources that are available for developers. I've not used everything on this list myself so don't take this as personal endorsement.

Templates

  • Entity Developer
    Add-in for Visual Studio that provides a replacement designer with code templates. Commercial ($99.95)
  • LLBLGen Pro
    This ORM templating and design tool has a set of LINQ to SQL templates available for generating C# code including file per entity that can be used in conjunction with their designer. Templates are free but require LLBLGen Pro licence (€179-249).
  • L2ST4
    My templates use Visual Studio's built in T4 engine and provide a great starting point to customizing the code generation process. Everything that SQL Metal/LINQ to SQL designer can generate is handled including C# and VB.NET generation and are freely licensed under the MS-PL.
  • PLINQO
    These templates for Eric Smith's ever-popular CodeSmith templating environment include a whole host of extra functionality beyond the standard generation including entity clone & detach, enum's from tables, data annotations, batching, auditing and more. Templates are free but require CodeSmith licence ($79-$299).
  • T4 Toolbox
    Oleg Sych has put together a suite of useful T4 templates including ones for producing LINQ to SQL entities, data contexts as well as SQL scripts for altering the schema to reflect changes. C# only, MS-RL.

Note: While the T4 templating language is built-in to Visual Studio 2008/2010 it does not come with syntax highlighting or IntelliSense. Check out either:

  • Clarius Visual T4
    Basic ‘community’ version available for free, commercial ‘pro’ version with IntelliSense, sub-templates, preview, user preferences etc. is $99.
  • Tangible T4
    Free version available with limited IntelliSense, commercial ‘pro’ version with UML modelling etc. available for $99.

Blogs

  • David DeWinter
    David is a dev in test who recently joined our team and hit the ground running with testing, blogging and helping out on the forums.
  • Roger Jennings
    Roger over at OakLeaf Systems publishes regular articles and roundups of some of the best .NET data access content from around the web including LINQ to SQL.
  • Scott Guthrie
    Our Corporate Vice President for the .NET Developer Platform takes a very active role in getting his hands dirty and publishes a series of useful LINQ to SQL articles.
  • Sidar Ok
    Sidar is a regular forum helper and has written a number of great posts on LINQ to SQL including some good POCO coverage.

Tools

  • Devart dotConnect
    Devart's dotConnect family are database providers for Oracle, MySQL, Postgres and SQLite that also include LINQ support to enable LINQ to SQL like functionality on other platforms. Some database basic versions are free, professional versions are commercial and vary in price (~$99-$209).
  • Hugati DBML/EDMX Tools
    Add-in for Visual Studio that provides comparison/update facilities between the database and the DBML as well as standardising names and generating interfaces. Commercial ($49-$119, free 30 day trial).
  • Hugati LINQ to SQL Profiler
    Profiling tool to help optimize your LINQ to SQL based applications. Commercial ($49-$119, free 45 day trial).
  • LINQpad
    This invaluable tool helps you write and visualise your LINQ queries in a test-bench without compilation and includes a version for the .NET 4.0 beta. Free to use, auto-completion add-on available ($19).

Official guides

  • Samples
    The official samples includes a whopping 101 snippets showing how to use many of the features and syntax.
  • Programming Guide
    Includes steps on how to get started, querying, making changes, debugging and background information.
  • Whitepaper
    Single document describing the architecture, query capabilities, change tracking and lifecycle, multi-tier entities, external mapping etc.

Books

Support

  • Official MSDN forums
    Great way to get access to the product team directly as well as knowledgeable and experienced users if you have a question or a problem.
  • Official LINQ to SQL FAQ 
    Coverage is a little thin on the ground but it has some useful tips.
  • StackOverflow's LINQ to SQL tag
    StackOverflow has rapidly become a leader in questions and answers for a wide variety of developer topics and covers LINQ to SQL (which the site uses for it's data access too!)

[)amien

01
Jun

LINQ to SQL changes in .NET 4.0

People have been asking via Twitter and the LINQ to SQL forums so here’s a list I put together on a number of the changes made for 4.0.

Change list

Performance

  • Query plans are reused more often by specifically defining text parameter lengths
  • Identity cache lookups for primary key with single result now includes query.Where(predicate).Single/SingleOrDefault/First/FirstOrDefault
  • Reduced query execution overhead when DataLoadOptions specified (cache lookup considers DataLoadOptions value equivalency – post beta 1)

Usability

  • ITable<T> interface for additional mocking possibilities
  • Contains with enums automatically casts to int or string depending on column type
  • Associations can now specify non-primary-key columns on the other end of the association for updates
  • Support list initialization syntax for queries
  • LinqDataSource now supports inherited entities
  • LinqDataSource support for ASP.NET query extenders added

Query stability

  • Contains now detects self-referencing IQueryable and doesn't cause a stack overflow
  • Skip(0) no longer prevents eager loading
  • GetCommand operates within SQL Compact transactions
  • Exposing Link<T> on a property/field is detected and reported correctly
  • Compiled queries now correctly detect a change in mapping source and throw
  • String.StartsWith, EndsWith and Contains now correctly handles ~ in the search string
  • Now detects multiple active result sets (MARS) better
  • Associations are properly created between entities when using eager loading with Table-Valued Functions (TVFs)
  • Queries that contain sub-queries with scalar projections now work better

Update stability

  • SubmitChanges no longer silently consumes transaction rollback exceptions
  • SubmitChanges deals with timestamps in a change conflict scenario properly
  • IsDbGenerated now honors renamed properties that don't match underlying column name
  • Server-generated columns and SQL replication/triggers now work instead of throwing SQL exception

General stability

  • Binary types equate correctly after deserialization
  • EntitySet.ListChanged fired when adding items to an unloaded entity set
  • Dispose our connections upon context disposal (ones passed in are untouched)

SQL Metal

  • Foreign key property setter now checks all affected associations not just the first
  • Improved error handling when primary key type not supported
  • Now skips stored procedures containing table-valued parameters instead of aborting process
  • Can now be used against connections that use AttachDbFilename syntax
  • No longer crashes when unexpected data types are encountered

LINQ to SQL class designer

  • Now handles a single anonymously named column in SQL result set
  • Improved error message for associations to nullable unique columns
  • No longer fails when using clauses are added to the partial user class
  • VarChar(1) now correctly maps to string and not char
  • Decimal precision and scale are now emitted correctly in the DbType attributes for stored procedures
  • Foreign key changes will be picked up when bringing tables back into the designer without a restart

Code generation (SQL Metal + LINQ to SQL class designer)

  • Stored procedures using original values now compiles when the entity and context namespaces differ
  • Virtual internal now generates correct syntax
  • Mapping attributes are now fully qualified to prevent conflicts with user types
  • KnownTypeAttributes are now emitted for DataContractSerializer with inheritance
  • Delay-loaded foreign keys now have the correct, compilable, code generated
  • Using stored procedures with concurrency no longer gets confused if entities in different namespace to context
  • ForeignKeyReferenceAlreadyHasValueException is now thrown if any association is loaded not just the first

Potentially breaking changes

We worked very hard to avoid breaking changes but of course any potential bug fix is a breaking change if your application was depending on the wrong behavior. The ones I specifically want to call out are:

Skip(0) is no longer a no-op

The special-casing of 0 for Skip to be a no-op was causing some subtle issues such as eager loading to fail and we took the decision to stop special casing this. This means if you had syntax that was invalid for a Skip greater than 0 it will now also be invalid for skip with a 0. This makes more sense and means your app would break on the first page now instead of subtlety breaking on the second page. Fail fast :)

ForeignKeyReferenceAlreadyHasValue exception

If you are getting this exception where you weren’t previously it means you have an underlying foreign key with multiple associations based on it and you are trying to change the underlying foreign key even though we have associations loaded.Best thing to do here is to set the associations themselves and if you can’t do that make sure they aren’t loaded when you want to set the foreign key to avoid inconsistencies.

[)amien

07
May

Font hinting and instructing – a primer

Taking my bitmap font Envy Code B into the vector TrueType Envy Code R was a long process, the most difficult being hinting.

Bitmap v scalable fonts

Bitmap fonts are incredibly easy to make. Using a program like Softy or BitFonter you decide the size of your letters and start plotting pixels. You can see exactly how it will look because you draw every glyph (letter/symbol/number) in every size you want to support. This can obviously be very time consuming and doesn’t let you take full advantage of the resolution of the device and the capabilities it offers. A printer can handle in excess of 300 dpi while a display is typically 72 dpi (Mac) or 96 dpi (Windows) with LCD’s supporting sub-pixels due to the individual layout of the red-green and blue elements you can’t feasibly pre-plot every single combination and even if you could the file size would be rather large.

Rather than having specific set of pixels to turn on or off TrueType, OpenType and PostScript fonts contain a series of instructions that tell the computer the shape using a series of points, lines and curves. This means the computer can scale the glyph to the size that is required and then take full advantage of the device being rendered honoring the users preferences for anti-aliasing (smoothing using shades of grey), sub-pixel precision (smoothing using hints of red, green and blue to take advantage of the layout of colour elements in an LCD display), desired contrast and gamma settings etc.

Grid fitting

Such a scaled glyph won’t fit perfectly within a pixel grid and a small sizes and low resolution it can look awful. It is also necessary to ensure that the vertical part of the letter I (known as a stem) looks very similar to the stem of other letters at the same size – we don’t want some letters looking bold – and that the top of the letter o aligns nicely with the top of the i etc. (in most fonts). The glyphs themselves don’t know what is a stem, what should align with other glyphs etc.

Many renders include logic to try and improve un-hinted fonts such as the drop-out control in Windows through to the full auto-hinter in FreeType. If you’ve ever used free fonts from any of the numerous web sites around you’ve probably seen that it doesn’t get it right and it looks like this: Envy Code R unhinted

The first few versions of Envy Code R looked like that because to address this problem you need to learn a process called hinting, which let’s the designer give the renderer “hints” on how to choose the pixels.

Hinting

Font hinting started off as stem and edge identification so that glyphs would maintain the right proportions when sized and rendered on these low-DPI devices. It became apparent that a much more fine-grained level of control was required and so a stack-based byte-code language was developed as part of the TrueType specification to allow designers finer control in how points are adjusted to better take advantage of the display characteristics.

A TrueType font can contain extra blocks which describes, using a sequence of bytes that represent instructions and their arguments, the process by which to align the points and therefore make decisions about how best to fit the letter into the grid by retaining and adjusting various elements.

The important blocks are:

Block Name Description
fpgm Font program Run once when font first used to setup the tables.
gasp Grid-fitting and scan conversion Table specifying when to apply smoothing and grid-fitting based on size ranges.
prep Control value program Run every time the font needs to be drawn differently (e.g. change of size, changing anti-aliasing etc)
cvt Control value table Set of tables that can be used to specify various heights, widths, spacing, positions etc. that glyphs can relate to.

Each instruction (opcode) has a mnemonic that is representative of what it does and these are documented in Chapters 5 through 6 of the TrueType specification (along with much other useful relevant information). Actual per-glyph instructions are stored with each glyph outline in the glyp block.

Rasterizing & rendering

There are many different ways a TrueType font can end up on your screen with a lot of variants between how vendors chose to render the font and what options they expose to developers and users to fine-tune the experience.

  • Windows – User choice of 1-bit, 4-bit grey-scale anti-aliasing, ClearType, ClearType tuning and display DPI plus WPF and DirectWrite per-app options
  • Mac OS X – User choice of sub-pixel anti-aliasing strength and 1-bit cut-off plus per-app 1-bit option (e.g. Terminal)
  • Java – Per-application choice of 1-bit, grey-scale or sub-pixel rendering
  • Flash – Per-application choice of 1-bit or grey-scale
  • FreeType – Rendering library that exposes a number of runtime and compile-time settings

This is of course ignoring the other rendering engines out there such as the Adobe’s Photoshop, RiscOS, D-Type rendering engine, Font Fusion (used on BeOS) etc. and prior versions of those renderers listed above (Flash and Mac OS changed significantly). Getting it pixel-perfect on every combination is impossible but we can try :)

Tools

Instructing fonts is a painstaking process at the best of times and few people deal directly with the low-level instructions instead relying on tools, stem identification and higher-level languages to achieve the same result. Some tools that have support for hinting instructions are:

  • FontLab Studio 5
    Comprehensive font-production package for Windows and Mac that includes auto-hinting and it’s own higher-level link language that it can generate TrueType instructions from but it does not support viewing or modifying existing TrueType instructions and does not handle diagonals well. Rendering preview includes mono, grey-scale and ClearType. (Commercial $649)
  • Fontographer 4.1
    Rather dated font-production package for Windows and Mac. (Commercial $349)
  • FontForge
    Comprehensive font-production package that runs on X11 that includes auto-hinting and the ability to disassemble and edit existing TrueType instructions as well as debug them with stepping. Includes basic mono/grey-scale rendering options. (Open source)
  • Microsoft Visual TrueType
    Hinting instruction tool from Microsoft that uses it’s own higher-level VTT Talk language that compiles down to TrueType instructions that you can further edit. Includes a comprehensive set of preview rendering options but is not capable of disassembling existing instructions. (Commercial, free with signed licence agreement)
  • TTX
    Python scripts that can convert a font into an editable XML representation and back including disassembly and assembly of TrueType hinting instructions. (BSD)
  • TTIComp
    Command-line tool that provides an alternative C-like hinting language. (GPL)
  • Xgridfit
    FontForge scripts to provide an alternative XML-based hinting language. (GPL)
  • TrueTypeViewer
    Windows tool for displaying TrueType fonts and glyphs including debugging and descriptive disassembly of instructions. (GPL)
  • TTHMachine
    Real-time editing of hinting instruction mnemonics and observing their effects which is useful for learning. (Free, no longer supported)

[)amien

12
Apr

LINQ to SQL tips and tricks #2

A few more useful and lesser-known techniques for using LINQ to SQL.

Take full control of  the TSQL

There are times when LINQ to SQL refuses to cook up the TSQL you wanted either because it doesn’t support the feature or because it has a different idea what makes an optimal query.

In either case the Translate method allows you to deliver your own TSQL to LINQ to SQL to process as if it were its own with execution, materialization and identity mapping still honored. For example:

var db = new PeopleContext();
if (db.Connection.State == System.Data.ConnectionState.Closed)
    db.Connection.Open();
var cmd = db.GetCommand(db.Persons.Where(p => p.CountryID == 1));
cmd.CommandText = cmd.CommandText.Replace("[People] AS [t0]", "[People] AS [t0] WITH (NOLOCK)");
var results = db.Translate<Person>(cmd.ExecuteReader());

Complex stored procedures

When working with stored procedures the LINQ to SQL designer and SQLMetal tools need a way of figuring out what the return type will be. In order to do this without actually running the stored procedure itself they use the SET FMTONLY command set to ON so that SQL Server will just parse the stored procedure instead.

Unfortunately this parsing does not extend to tdynamic SQL or temporary tables so you must change the return type from the scalar integer to one of the known entity types by hand. You could use the following command at the start to let it run regardless given the subsequent warning.

SET FMTONLY OFF

If your stored procedure can not safely handle being called at any time with null parameters set the return type by hand instead.

Cloning an entity

There are many reasons you might want to clone an entity – you may want to create many similar ones, you could want to keep it around longer than the DataContext it came from – whatever your reason implementing a Clone method can be a pain but taking advantage of the DataContractSerializer can make light work of this providing your DBML is set to enable serialization.

If you use discriminator subclassing you will need to either ensure your type is cast to its concrete type or use my L2ST4 templates for now as .NET 3.5 SP1 doesn’t emit the necessary KnownType attributes to make this automatically happen (fixed in .NET 4.0). Add a simple method to serialize in-memory like this:

public static T Clone<T>(T source) {
    var dcs = new System.Runtime.Serialization.DataContractSerializer(typeof(T));
    using (var ms = new System.IO.MemoryStream()) {
        dcs.WriteObject(ms, source);
        ms.Seek(0, System.IO.SeekOrigin.Begin);
        return (T)dcs.ReadObject(ms);
    }
}

And then to clone simply:

var source = myQuery.First();var cloned = Clone(source);

Be aware that this comes with a little overhead in the serialization and deserialization process.

If that is a problem for you then why not grab those templates and make your entities implement ICloneable!

[)amien





Topics