Ho scritto il seguente metodo.C# LINQ a SQL: refactoring di questo metodo GetByID generico
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);
}
Fondamentalmente si tratta di un metodo in una classe generica in cui T
è una classe in un DataContext.
Il metodo ottiene la tabella dal tipo di T (GetTable
) e verifica la prima proprietà (sempre l'ID) al parametro immesso.
Il problema di questo è che ho avuto per convertire la tavola degli elementi di una lista prima di eseguire un GetType
sulla proprietà, ma questo non è molto conveniente perché tutti gli elementi della tavola devono essere enumerati e convertito in un List
.
Come posso refactoring questo metodo per evitare un sull'intera tabella?
[Update]
Il motivo non riesco a eseguire l'Where
direttamente sul tavolo è perché ricevo questa eccezione:
MODALITA 'System.Reflection.PropertyInfo [] GetProperties () "non ha traduzione supportata in SQL.
Perché GetProperties
non può essere convertito in SQL.
[Update]
Alcune persone hanno suggerito di usare un'interfaccia per T, ma il problema è che il parametro T
sarà una classe che viene generato automaticamente in [DataContextName] .designer.cs, e quindi non riesco a farlo implementare un'interfaccia (e non è fattibile implementare le interfacce per tutte queste "classi di database" di LINQ, e inoltre, il file verrà rigenerato una volta aggiunte nuove tabelle al DataContext, perdendo così tutte le dati scritti).
Quindi, ci deve essere un modo migliore per fare questo ...
[Update]
ora ho implementato il mio codice come Neil Williams 'suggerimento, ma sto ancora problemi .Ecco alcuni estratti del codice:
Interfaccia:
public interface IHasID
{
int ID { get; set; }
}
DataContext [Visualizza codice]:
namespace MusicRepo_DataContext
{
partial class Artist : IHasID
{
public int ID
{
get { return ArtistID; }
set { throw new System.NotImplementedException(); }
}
}
}
metodo generico:
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));
}
}
L'eccezione viene gettata su questa linea: return table.SingleOrDefault(e => e.ID.Equals(id));
e l'eccezione è:
System.NotSupportedException: The member 'MusicRepo_DataContext.IHasID.ID' has no supported translation to SQL.
[Aggiornamento] Soluzione:
Con l'aiuto di Denis Troller 's postato risposta e il link al post allo Code Rant blog, finalmente sono riuscito a trovare una soluzione:
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();
}
Non è necessario preoccuparsi di generare il progettista file o il progettista edmx oltre a scrivere di loro .. non si implementano l'interfaccia nel file di progettazione che si .. scriveremo una classe parziale per le entità che implementano l'interfaccia. – meandmycode
Ma ciò significa che dovrei rendere ogni "classe db" implementare questa interfaccia, no? –
Sì, sì, ma è un pezzo di lavoro e quindi il tuo codice sarà molto più robusto. –