I'm writing a LINQ to SQL based repository where I want to allow a GetByID with an int parameter. The signature is:
public T GetByID(int id)
{
// Return
return _dataContext.GetTable<T>() ....;
}
My tables have different names for the primary key. What I'd like to do is determine dynamically for each T what the primary key is and query it for a value of integer = id. Any ideas how to best pull this off?
Something like below (which supports other types than just int
, but defaults to int
). Importantly, don't fall into the trap of looking at Attribute
data via reflection; LINQ-to-SQL supports objects without attributes too:
public static TEntity Get<TEntity>(this DataContext dataContext, int id)
where TEntity : class
{
return Get<TEntity, int>(dataContext, id);
}
public static TEntity Get<TEntity, TKey>(this DataContext dataContext, TKey id)
where TEntity : class
{
// get the row from the database using the meta-model
MetaType meta = dataContext.Mapping.GetTable(typeof(TEntity)).RowType;
if (meta.IdentityMembers.Count != 1) throw new InvalidOperationException(
"Composite identity not supported");
string idName = meta.IdentityMembers[0].Member.Name;
var param = Expression.Parameter(typeof(TEntity), "row");
var lambda = Expression.Lambda<Func<TEntity, bool>>(
Expression.Equal(
Expression.PropertyOrField(param, idName),
Expression.Constant(id, typeof(TKey))), param);
return dataContext.GetTable<TEntity>().Single(lambda);
}
Dennis Troller answered it to the question that Ben linked to in the comments in the question.
Personally, I think it would be easier to provide a SingleOrDefault<T>
method that takes a Func<int,T>
selector argument. Then you can provide whatever selector you wish, including the one that selects based on that table's id.
public abstract class Repository<T> where T : class
{
public abstract T GetById( int id );
public T SingleOrDefault( Func<int,T> selector )
{
return _dataContext.GetTable<T>().SingleOrDefault( selector );
}
}
Usage:
var myObj = repos.SingleOrDefault<MyClass>( c => c.MyClassID == id );
A strongly-typed respository could then use this method to implement GetById()
public class MyClassRepository : Repository<MyClass>
{
public override MyClass GetById( int id )
{
return this.SingleOrDefault( c => c.MyClassID == id );
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With