views:

58

answers:

1

I'm not entirely sure the title is properly worded, but here's the situation... I noticed today while trying to create a generic save function for Linq to Sql that when I use lambda against a data context select. It breaks within a generic function with a type constraint of another generic interface. However, it works fine with LINQ syntax. I'm posing this question more or less to get an understanding of why this happens.

The exception being thrown is:
NotSupportedException
The mapping of interface member IEntity`1.ID is not supported.

The code involved looks similar to this (simplified):
The error causing function is GenericFunc<T>


//Assume SomeTable is generated from a DBML L2S file.

//partial extension of the L2S class
public partial class SomeTable : IEntity<SomeTable> { }

//interface to expose shared properties in these entity classes
public interface IEntity<T> where T : class
{
    //isolated application, int Primary key for all these tables.
    int ID { get; set; } 
}

//simple helper class for L2S stuff.
public class Repository
{
    //helper for inserting/updating data..
    public void SaveSomeTable(SomeTable data)
    {
        SomeDataContext db = new SomeDataContext();
        GenericFunc<SomeTable>(db.SomeTables, data);
    }

    //toy function for this example
    public void GenericFunc<T>(System.Data.Linq.Table<T> table, T data) where T : class, IEntity<T>, new ()
    {
        //note the generic type constraints... 
        //in this case, all table entities conform to the IEntity<T> class.

        //breaks
        var row = table.SingleOrDefault(o => o.ID == data.ID); 

        //works
        var row1 = (from item in table where item.ID == data.ID select item).SingleOrDefault();

        //... more stuff.
    }
}

+1  A: 

This isn't really a lambda issue. Here's non-query-syntax which will work too:

var row1 = table.Where(o => o.ID == data.ID)
                .SingleOrDefault();

That compiles to the same code as the query expresion, basically.

I strongly suspect it's a different code path for SingleOrDefault (internally) which gives problems.

Jon Skeet
doh! Hah! I didn't even notice I was doing that. I was comparing apples to oranges. Anyways, it is curious that the predicate for SingleOrDefault would cause that issue. I think you're right that it's internal to that function. Thanks!
Nathan