C # LINQ to SQL: Refatorando esse método GetByID genérico

Eu escrevi o seguinte método.

public T GetByID(int id)
{
    var dbcontext = DB;
    var table = dbcontext.GetTable<T>();
    return table.ToList().SingleOrDefault(e => Convert.ToInt16(e.GetType().GetProperties().First().GetValue(e, null)) == id);
}

Basicamente, é um método em uma classe genérica em queT é uma classe em um DataContex

O método obtém a tabela do tipo de T GetTable) e verifica a primeira propriedade (sempre sendo o ID) para o parâmetro inserid

O problema é que eu tive que converter a tabela de elementos em uma lista primeiro para executar umGetType na propriedade, mas isso não é muito conveniente, porque todos os elementos da tabela precisam ser enumerados e convertidos emList.

Como posso refatorar esse método para evitar umToList em toda a mesa?

[Atualizar

O motivo pelo qual não consigo executar oWhere diretamente na tabela é porque recebo esta exceção:

Method 'System.Reflection.PropertyInfo [] GetProperties ()' não tem tradução suportada para SQL.

PorqueGetProperties não pode ser traduzido para SQL.

[Atualizar

Algumas pessoas sugeriram o uso de uma interface paraT, mas o problema é que oT será uma classe gerada automaticamente em [DataContextName] .designer.cs e, portanto, não posso implementar uma interface (e não é possível implementar as interfaces para todas essas "classes de banco de dados" do LINQ; além disso, o arquivo será regenerado assim que eu adicionar novas tabelas ao DataContext, perdendo assim todo o dados escritos).

Então, tem que haver uma maneira melhor de fazer isso ...

[Atualizar

Agora implementei meu código comoNeil Williams 'sugestão, mas ainda estou tendo problemas. Aqui estão trechos do código:

Interface

public interface IHasID
{
    int ID { get; set; }
}

DataContext [ver código]:

namespace MusicRepo_DataContext
{
    partial class Artist : IHasID
    {
        public int ID
        {
            get { return ArtistID; }
            set { throw new System.NotImplementedException(); }
        }
    }
}

Método genérico:

public class DBAccess<T> where T :  class, IHasID,new()
{
    public T GetByID(int id)
    {
        var dbcontext = DB;
        var table = dbcontext.GetTable<T>();

        return table.SingleOrDefault(e => e.ID.Equals(id));
    }
}

A exceção está sendo lançada nesta linha:return table.SingleOrDefault(e => e.ID.Equals(id)); e a exceção é:

System.NotSupportedException: The member 'MusicRepo_DataContext.IHasID.ID' has no supported translation to SQL.

Solução [Update]:

Com a ajuda deDenis Troller resposta de @ postada e o link para a postagem noCode Rant blog, Finalmente consegui encontrar uma solução:

public static PropertyInfo GetPrimaryKey(this Type entityType)
{
    foreach (PropertyInfo property in entityType.GetProperties())
    {
        ColumnAttribute[] attributes = (ColumnAttribute[])property.GetCustomAttributes(typeof(ColumnAttribute), true);
        if (attributes.Length == 1)
        {
            ColumnAttribute columnAttribute = attributes[0];
            if (columnAttribute.IsPrimaryKey)
            {
                if (property.PropertyType != typeof(int))
                {
                    throw new ApplicationException(string.Format("Primary key, '{0}', of type '{1}' is not int",
                                property.Name, entityType));
                }
                return property;
            }
        }
    }
    throw new ApplicationException(string.Format("No primary key defined for type {0}", entityType.Name));
}

public T GetByID(int id)
{
    var dbcontext = DB;

    var itemParameter = Expression.Parameter(typeof (T), "item");
    var whereExpression = Expression.Lambda<Func<T, bool>>
        (
        Expression.Equal(
            Expression.Property(
                 itemParameter,
                 typeof (T).GetPrimaryKey().Name
                 ),
            Expression.Constant(id)
            ),
        new[] {itemParameter}
        );
    return dbcontext.GetTable<T>().Where(whereExpression).Single();
}

questionAnswers(6)

yourAnswerToTheQuestion