Hi everyone,
Trying to use Linq to SQL for a small project I'm working on at home. I have generated a the context code and all my entity classes using dbmetal.exe (from the DBLinq project) against a local MySQL database.
Everything is working great, but I'm trying to abstract some redundant code and I'm running into issues trying to do so.
Basically all my entities are of type Table in my context class. For example I have Table and Table.
While I was architecting the various interfaces for the repository behaviors I realized that there some methods that were very redundant with each entity. For example the ID field:
User findById(int id);
Calendar findById(int id);
I designed my tables so they all have 3 fields in common [ID, DATECREATED, DATEUPDATED]. Since those fields are common I wanted to have a common behavior instead of rewriting those methods for each entity.
So I made my repository classes (UserRepository, CalendarRepository) inherit a common "Repository" class that's defined like that:
public class Repository<T> : IDisposable, IRepository<T> where T : class
{
protected MyContext context;
private DbLinq.Data.Linq.Table<T> currentTable;
protected Repository() {
context = new MyContext();
Type currentType = this.GetType().GetGenericArguments()[0];
currentTable = //Set currentTable based on currentType. e.g.: currentTable = context.User;
}
#region IRepository<T> Members
public T findById(int? id)
{
return currentTable.SingleOrDefault(d => d.ID == id);
}
public T findByDateCreated(DateTime dateCreated)
{
return currentTable.SingleOrDefault(d => DateTime.Equals(dateCreated, d.DateCreated));
}
public T findByDateUpdated(DateTime dateUpdated)
{
return currentTable.SingleOrDefault(d => DateTime.Equals(dateUpdated, d.DateUpdated));
}
public T insert(T domainObject)
{
currentTable.InsertOnSubmit(domainObject);
return domainObject;
}
public T save(T domainObject)
{
context.SubmitChanges();
return domainObject;
}
#endregion
#region IDisposable Members
public void Dispose()
{
if (context != null)
context.Dispose();
}
#endregion
}
Well it turns out this is more difficult than I thought. When I try to set:
currentTable = (Table<T>)context.User;
I get the following error:
Cannot convert type 'DbLinq.Data.Linq.Table<Models.Domain.User>' to 'DbLinq.Data.Linq.Table<T>'
Implicit casting does not work either.
Anyone has ever done something similar successfully? That'd be very sad if I had to have all my Repository classes implement the same findById method with exactly the same code in it... I'm sure there is a way to NOT do that, I just can't find it. :)