tags:

views:

542

answers:

4

Hi all

Is there a way to do this

public T GetItemById(int id)
{
    Table<T> table = _db.GetTable<T>();
    table.Where(t => t.Id == id);
}

Note that i.Id does not exist in the context as linq does not know what object it is working with, and Id is the primary key of the table

A: 

Maybe you can find something under Generic Predicates, at http://www.albahari.com/nutshell/predicatebuilder.aspx. It's the last section on the page.

Svish
A: 
var X = _db.table.Select(i => i.Id == id);

this will return IQueryable< T>

roman m
Yes but (i.Id) does not exist in the current context as _db.table is generic :)
can you elaborate on the usage of your method?
roman m
forget about it ... Jon Skeet is here :)
roman m
+1  A: 

(removed approach bound to attributes)

edit: and here's the meta-model way (so it works with mapping files as well as attributed objects):

static TEntity Get<TEntity>(this DataContext ctx, int key) where TEntity : class
{
    return Get<TEntity, int>(ctx, key);
}
static TEntity Get<TEntity, TKey>(this DataContext ctx, TKey key) where TEntity : class
{
    var table = ctx.GetTable<TEntity>();
    var pkProp = (from member in ctx.Mapping.GetMetaType(typeof(TEntity)).DataMembers
                  where member.IsPrimaryKey
                  select member.Member).Single();
    ParameterExpression param = Expression.Parameter(typeof(TEntity), "x");
    MemberExpression memberExp;
    switch (pkProp.MemberType)
    {
        case MemberTypes.Field: memberExp = Expression.Field(param, (FieldInfo)pkProp); break;
        case MemberTypes.Property: memberExp = Expression.Property(param, (PropertyInfo)pkProp); break;
        default: throw new NotSupportedException("Invalid primary key member: " + pkProp.Name);
    }
    Expression body = Expression.Equal(
        memberExp, Expression.Constant(key, typeof(TKey)));
    var predicate = Expression.Lambda<Func<TEntity, bool>>(body, param);
    return table.Single(predicate);
}
Marc Gravell
+2  A: 

You'd need to create an appropriate interface which the entities derive from (unless you want to do it with an expression tree like Marc's example):

public interface IIdentifiedEntity
{
    int Id { get; } // Set as well? Depends on your situation.
}

Then you can write:

public T GetItemById<T>(int id) where T : class, IIdentifiedEntity
{
    Table<T> table = _db.GetTable<T>();
    return table.Where(t => t.Id == id)
                .Single();
}
Jon Skeet
uhm please note this is a class public class RepositoryBase<T> where T : cla
The problem with this approach is that it only works for implicit interface implementations...
Marc Gravell
(i.e. you can't have the IIdentifiedEntity.Id map to Foo.FooID)
Marc Gravell
yeah but all my primary keys are Id so I dont think I will have a issue?
In that case, this approach will work. Note that you can either write a partial class for each, or you can edit the dbml to specify a base-class [sic] of "IIdentifiedEntity" for the entities.
Marc Gravell
The question is tho public ActionResult Delete(int id) { Models.Service _service = new DataAccess.ServiceRepository().GetItemById<Models.Service>(id); GetItemById<T>?
I need to learn some generics :)
how would one execute this method tho?
Customer cust = GetItemById<Customer>(12345);(if you make it an instance method of the data-context, replace "_db" with "this")
Marc Gravell