Ich versuche, mit Dapper ein generisches Repository zu erstellen. Ich habe jedoch einige Schwierigkeiten, die CRUD-Operationen zu implementieren.
Hier ist ein Code aus dem Repository:
public class GenericRepository<TEntity> : IGenericRepository<TEntity> where TEntity : class
{
internal IDbConnection Connection
{
get
{
return new SqlConnection(ConfigurationManager.ConnectionStrings["SoundyDB"].ConnectionString);
}
}
public GenericRepository(string tableName)
{
_tableName = tableName;
}
public void Delete(TEntity entity)
{
using (IDbConnection cn = Connection)
{
cn.Open();
cn.Execute("DELETE FROM " + _tableName + " WHERE Id=@ID", new { ID = entity.Id });
}
}
}
Wie Sie sehen können, verwendet meine Löschmethode eine TEntity als Parameter, der ein Parameter der Typklasse ist.
Ich rufe meine Delete-Methode aus meinem UserRepository folgendermaßen auf:
public class UserRepository : GenericRepository<User>, IUserRepository
{
private readonly IConnectionFactory _connectionFactory;
public UserRepository(IConnectionFactory connectionFactory) : base("User")
{
_connectionFactory = connectionFactory;
}
public async Task<User> Delete(User model)
{
var result = await Delete(model);
return result;
}
}
Die Sache ist, dass ich keine entity.Id
schreiben kann. entity.Id
in meiner Delete-Operation in meinem generischen Repository. Ich bekomme eine Fehlermeldung. Wie kann ich CRUD-Operationen wie diese einfach implementieren?
Hier ist die Fehlermeldung:
TEntity enthält keine Definition von "Id" und es konnte keine Erweiterungsmethode "Id" gefunden werden, die ein Argument vom Typ "TEntity" akzeptiert
Definieren Sie eine Schnittstelle wie folgt.
public interface ITypeWithId {
int Id {get;}
}
Und stellen Sie sicher, dass Ihr User
diese Schnittstelle implementiert.
Wenden Sie es nun als generische Einschränkung auf Ihre Klasse an.
public class GenericRepository<TEntity> : IGenericRepository<TEntity> where TEntity : class, ITypeWithId
Wenn Sie über Typen verfügen, die im Repository gespeichert sind, aber keine ID-Eigenschaft aufweisen, legen Sie die Einschränkung für den Löschertyp für die Methode und nicht für die Klasse fest. Auf diese Weise können Sie den gleichen Repository-Typ auch mit Typen verwenden, die auf etwas anderes wie eine Zeichenfolge oder einen zusammengesetzten (Multi-) Schlüssel zugreifen können.
public void Delete<T>(T entity) where T : class, ITypeWithId
{
using (IDbConnection cn = Connection)
{
cn.Open();
cn.Execute("DELETE FROM " + _tableName + " WHERE Id=@ID", new { ID = entity.Id });
}
}
Bitte tu das nicht! Ihr generisches Repository fügt mehr Verwirrung als Wert hinzu. Es ist ein fragiler Code (String-Literale für _tableName, ungültige Cast-Fehler im ID-Parameter) und führt zu einer klaffenden Sicherheitslücke (SQL-Injektion über _tableName). Wenn Sie sich für Dapper entschieden haben, liegt das daran, dass Sie die Kontrolle über Ihren SQL-Server haben möchten. Es macht also keinen Sinn, den SQL-Server zu generieren, den Sie an Dapper senden.