Определить первичный ключ, используя LINQ to SQL - PullRequest
5 голосов
/ 08 августа 2009

Я пишу репозиторий на основе LINQ to SQL, где я хочу разрешить GetByID с параметром int. Подпись:

public T GetByID(int id)
{
     // Return
     return _dataContext.GetTable<T>() ....;
}

Мои таблицы имеют разные имена для первичного ключа. Что я хотел бы сделать, это определить динамически для каждого T, что является первичным ключом, и запросить его для значения integer = id. Есть идеи, как лучше всего это осуществить?

Ответы [ 3 ]

10 голосов
/ 08 августа 2009

Пример ниже (который поддерживает другие типы, кроме int, но по умолчанию int). Важно отметить, что не попадитесь в ловушку, глядя на Attribute данные через отражение; LINQ-to-SQL также поддерживает объекты без атрибутов:

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);
}
3 голосов
/ 08 августа 2009

Лично я думаю, что было бы проще предоставить метод SingleOrDefault<T>, который принимает аргумент селектора Func<int,T>. Затем вы можете предоставить любой селектор, который вы пожелаете, включая тот, который выбирается на основе идентификатора этой таблицы.

 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 );
     }
 }

Использование:

 var myObj = repos.SingleOrDefault<MyClass>( c => c.MyClassID == id );

Сильно типизированный репозиторий мог бы затем использовать этот метод для реализации GetById ()

 public class MyClassRepository : Repository<MyClass>
 {
     public override MyClass GetById( int id )
     {
         return this.SingleOrDefault( c => c.MyClassID == id );
     }
 }
3 голосов
/ 08 августа 2009

Деннис Троллер ответил на вопрос, на который Бен ссылался в комментариях к вопросу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...