Repository Design Pattern mit Dapper
Dies ist vielleicht eher eine Frage für code-review statt stack-überlauf.
Bin ich mit Dapper für ein MicroORM zum abrufen und Speichern von Daten in SQL Server 2014. Ich habe DTO-Klassen in ein DTO Proj vertreten, dass die abgerufenen Daten aus der DB oder in der DB gespeichert.
Ich bin mit dem Repository-Muster so an meinen Service-layer wird ein repository benötigt, bin ich mit dem Konstruktor DI, Spritzen, Abhängigkeit und rufen Sie dann die Methode auf das Repository, um die Arbeit zu tun.
also sagen wir ich habe 2 Dienste genannt CustomerService und CarService.
Dann habe ich 2 Repositories ein CustomerRepository und ein CarRepository.
Habe ich ein interface definiert alle Methoden, die in jedem Repository, und dann die konkreten Implementierungen.
Einer Beispiel-Methode ist unten dargestellt (ruft eine Gespeicherte Prozedur zu tun, die DB EINFÜGEN (Hinweis: der eigentliche string-variable für die gespeicherte Prozedur definiert ist als private string an der Spitze der Klasse):
public void SaveCustomer(CustomerDTO custDTO)
{
using (IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["myDB"].ConnectionString))
{
db.Execute(saveCustSp, custDTO, commandType: CommandType.StoredProcedure);
}
}
Dies alles funktioniert gut, aber ich finde mich wiederholen den using-block in jede Methode, die in jedem repository. Ich habe zwei richtige Fragen, die nachfolgend umrissen werden.
Gibt es eine bessere Methode, die ich verwenden könnte vielleicht irgendwie mit einem BaseRepository Klasse, die jedes andere Repository erbt und die Basis zur Umsetzung der Instanzierung des DB-Verbindung?
Wäre das noch ok, arbeiten für mehrere gleichzeitige Benutzer auf dem system?
****UPDATE****
Basierend auf Silas Antwort, die ich erstellt haben, den folgenden
public interface IBaseRepository
{
void Execute(Action<IDbConnection> query);
}
public class BaseRepository: IBaseRepository
{
public void Execute(Action<IDbConnection> query)
{
using (IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["myDB"].ConnectionString))
{
query.Invoke(db);
}
}
}
Jedoch in meinen repositories, ich habe andere Methoden wie zum Beispiel die folgenden:
public bool IsOnlyCarInStock(int carId, int year)
{
using (IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["myDB"].ConnectionString))
{
var car = db.ExecuteScalar<int>(anotherStoredSp, new { CarID = carId, Year = year },
commandType: CommandType.StoredProcedure);
return car > 0 ? true : false;
}
}
und
public IEnumerable<EmployeeDTO> GetEmployeeDetails(int employeeId)
{
using (IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["myDB"].ConnectionString))
{
return db.Query<EmployeeDTO>(anotherSp, new { EmployeeID = employeeId },
commandType: CommandType.StoredProcedure);
}
}
Was ist der richtige Weg, um diese zu meinem Base-repository mit Hilfe von Generischen Typ T, so konnte ich wieder jede Art von DTO oder C# Native Art
die
using
block ist ein notwendiges übel, weil man durch das öffnen von verbindungen zur Datenbank, die geschlossen werden müssen. Also die Wiederholung ist notwendig. Ich würde nur empfehlen, nicht verfangen in das gesamte repository design pattern-Zeug....welche anderen Muster würden Sie vorschlagen, oder könnte man mit einem Beispiel illustrieren. Ich sah Sie an mit CQRS, aber ich fühlte mich repository wie oben arbeitete für mich KUSS
Off-topic, aber CustomerDTO sollte CustomerDto. Klassen verwenden müssen PascalCase (wie von Microsoft empfohlen). Da die Abkürzung " DTO " ist größer als 2 Zeichen, die Sie brauchen, um es zu Dto.
InformationsquelleAutor Ctrl_Alt_Defeat | 2017-03-22
Du musst angemeldet sein, um einen Kommentar abzugeben.
Sicher, eine Funktion zu erstellen, und entsorgen Sie Ihre Verbindung funktioniert Super.
Und Ihre vereinfachten Aufruf Website:
Mit Rückgabewerten:
In Ihrem Ruf Website, schreiben Sie einfach die Logik, die Sie verwenden möchten.
Wenn Sie erwarten, dass viele Klassen, die diese Funktionalität benötigen, dann eine base-repository ist eine tolle Idee.
Aufrufen der Abfrage/Aktion Arbeit für alles, was Sie tun möchten, mit einem IDbConnection, einschließlich der beiden Dapper Methoden und nicht-Dapper Methoden.
Ich code Hinzugefügt, sollte der Griff einer Abfrage Szenarien.
Es hängt von Ihrem Anwendungsfall. Wenn Sie besorgt sind mit der Leistung und habe ein problem, führen Sie dann einen Profiler, um zu sehen, ob die Verwaltung die Verbindung manuell ist schneller. Im Allgemeinen, ich aufschieben der Entscheidung zu Dapper.
InformationsquelleAutor Silas Reinagel
Dies ist nicht direkt relevant für deine Frage. Aber ich schlage vor, Sie überlegen, DapperExtensions.
Zunächst habe ich umgesetzt Repository-pattern mit Dapper. Der Nachteil war, dass, ich habe das schreiben von Abfragen über alle; es war sehr faserig. Aufgrund der hart codierten Abfragen war es fast unmöglich zu schreiben generischen repository.
Vor kurzem rüstete ich meinen code zu verwenden DapperExtensions. Dies behebt sehr viele Probleme.
Folgenden wird die generische repository:
Wie Sie sehen können in obigen code die meisten Methoden sind nur wrapper über zugrunde liegende
DapperExtensionsProxy
Klasse.DapperExtensionsProxy
intern verwaltet auch UnitOfWork, die Sie unten sehen können. Diese beiden Klassen kombiniert werden können, ohne jede Frage. Ich persönlich bevorzuge, um Sie zu halten getrennt.Können Sie auch feststellen, dass zusätzliche Methoden
Exists
,DeleteById
, undDeleteAll
umgesetzt werden, sind diejenigen, die nicht Teil derDapperExtensionsProxy
.Methode
poco.SetDbId
definiert ist, in jedem POCO-Klasse, um Ihre Id-Eigenschaft. In meinem Fall, die Bezeichner von POCOs können unterschiedliche Datentypen und Namen.Folgenden ist
DapperExtensionsProxy
:Folgenden ist die
BasePoco
oben verwendet:Diese auch verwendet UnitOfWork dem erklärt wird,hier.
Keine änderung erforderlich, um diese Arbeit mit mehreren Datenbank-Instanzen. Beachten Sie, dass UnitOfWork injiziert, die in Repository wie diese
BaseRepository(IUnitOfWork unitOfWork)
. Sie können erstellen neue UnitOfWork für jede Datenbank-Instanz und injizieren es in der gleichen Klasse (neue Instanz des Repository) ohne jede änderung.Was ist BasePoco Klasse? in welchem Paket könnte es sein, gefunden?
Sie haben es auf git überall? @AmitJoshi
etwas iam falsch ich kann nicht sehen, Abb i.stack.imgur.com/4oGf8.png
InformationsquelleAutor Amit Joshi