locked
Linq and Generics RRS feed

  • Question

  • I have about 30 or so tables and I am using Linq to SQL. I wish to implement simple Get(Id) functions for each table in order to retrieve records from the table and thought I might be able to use generics to write this once and not have to repeat it 30 times. Here's what I've done:

     

    First, I declare an interface class

     

    Code Block

    public interface ISinglePrimaryKey<Key>

    {

    Key Id { get; set; }

    }

     

     

     

    I then implement a simple static class that implements the Get(id) function like so:

     

    Code Block

    public class GuidDataService

    where T : class, ISinglePrimaryKey<Guid>

    {

    static public T Get(Guid id)

    {

    MyDataContext ctx = new MyDataContext();

    Table table = ctx.GetTable<T>();

    return table.Single(c => c.Id == id);

    }

    }

     

     

    I then add the following declaration

     

    Code Block

    public partial class User : GuidDataService<User>, ISinglePrimaryKey<Guid> { }

     

    The User class is one of the 30 classes generated by Linq to SQL as a partial class. All my Tables that I intend to use in the above way have an "Id" column as the primary key. (The code compiles fine)

     

    At runtime, when I call User.Get(...) I get the following exception:

     

    System.NotSupportedException : The mapping of interface member ISinglePrimaryKey`1.Id is not supported.

     

    I'm obviously messing up the attribute mapping somehow by using the ISinglePrimaryKey interface or perhaps by inheriting from GuidDataService. Has anyone else had experience with this? Any idea how to solve this?

     

    I would like to use the above pattern for a number of other interfaces (Count, FindAll etc). Also, it's important to use a predicate that will be converted deep inside Linq into an SQL query where the database does the search and lookup of the entity by Id (versus retrieving all the rows and filtering in memory).

     

    Thanks for your help.

     

     

    Saturday, January 5, 2008 12:53 AM

Answers

  • I have faced this problem and I think it is a bug with construction of expression tree in Queryable.Single extension method. If you write a non-generic implementation of Get method, it works well!

    In order to avoid this exception, rewrite your table.Single(c => c.Id == id) as table.Where(c => c.Id == id).Single(). This works without any problems.

    Saturday, January 5, 2008 11:09 AM

All replies

  • I have faced this problem and I think it is a bug with construction of expression tree in Queryable.Single extension method. If you write a non-generic implementation of Get method, it works well!

    In order to avoid this exception, rewrite your table.Single(c => c.Id == id) as table.Where(c => c.Id == id).Single(). This works without any problems.

    Saturday, January 5, 2008 11:09 AM
  •  

    Awesome! That did it. Thank you very much.
    Sunday, January 6, 2008 4:04 AM