views:

280

answers:

3

I am trying to write a generic repository that will perform basic methods on all my linq2sql classes. (getById, insert, delete, getAll)

Im not so sure on how to get this done. Heres what I got so far... the getById method is giving me an error cause it cant relate Id attribute to 'T' class. I would appreciate some pointers on how to wrap my head around this generic class concept

    public class Repository<T> where T:class
{
    private ClassesDataContext db = new ClassesDataContext();


public IQueryable<T> getAll() 
{
    return db.GetTable<T>();
}
public T getById(int id)
{
    db.GetTable<T>().Where(e=>e.Id==id);
    return db.GetTable<T>().Single(c =>c.Id==id);
}}
A: 

Inside your repository class it will treat all instances of type T as an object (which doesn't have the Id property).

To have some generic support you can create a base entity class like this:

public abstract class EntityBase
{
    public int Id {get; private set; }
}

And make all entities that the repository will use inherit from this class.

You would then need to update your repository class definition to contain this where instead of the one you have:

public class Repository<T> where T: EntityBase

This will allow all instances of type T inside your repository methods to be treated as an EntityBase -which defines the Id method.

Craigerm
hey, that seems like it might be work... but I dont know how to instantiate the repository in my controllerRepository<Company> companyrepository = new Repository<Company>();gives me error
NachoF
Does your company class inherit form the EntityBase class ?
Craigerm
No, Company Class was automatically created as a linqtosql class with the designer... if it has to inherit from that then I guess Ill have to look for another approach
NachoF
A: 

You can not use lamba expression (Where clause in the getById method) to retrieve items becuase the properties are not know for type T.

You will have to build a SQL string and execute that.

string query = "SELECT * FROM [SomeTable] WHERE [SomeColumn] = {0}";
return db.ExecuteQuery<T>(query, id).FirstOrDefault();

You will have to get the TableName and PrimaryKeyName for type T. You can get the table name using the following:

db.Mapping.GetTable(typeof(T)).TableName;

You can get the list of primary key columns using:

db..Mapping.GetTable(typeof(T)).RowType.IdentityMembers.Select(m => m.MappedName).ToArray();

If you don't mind having each repository inheriate from a base class, you could simple set two fields for TableName and PrimaryKey.

It's alot of work to build a complete generic DAL/Repository for Linq2Sql. It really gets "fun" creating generic Save, Update methods for detached entities.

-Douglas H.

Douglas
Whoops, my mistake. I did not realize you were creating a specific DataContext for your database. I thought you were creating a generic DataContext class. Jirapong is correct then.
Douglas
+2  A: 

This must help you out - http://csainty.blogspot.com/2008/04/linq-to-sql-generic-primary-key.html

MyDataContext db = new MyDataContext();
Product p = db.GetByPk<Product>(1);
Jirapong