Derzeit baue ich eine Windows-Anwendung mit SQLite. In der Datenbank gibt es eine Tabelle sagen User
, und in meinem Code gibt es eine Repository<User>
und eine UserManager
. Ich denke, es ist ein sehr allgemeines Design. Im Repository gibt es eine List
Methode:zurück Queryable <T> oder Liste <T> in einem Repository <T>
//Repository<User> class
public List<User> List(where, orderby, topN parameters and etc)
{
//query and return
}
Dieses Problem bringt, wenn ich etwas komplexer in UserManager.cs
tun wollen:
//UserManager.cs
public List<User> ListUsersWithBankAccounts()
{
var userRep = new UserRepository();
var bankRep = new BankAccountRepository();
var result = //do something complex, say "I want the users live in NY
//and have at least two bank accounts in the system
}
Sie sehen können, Rückkehr List<User>
bringt Performance-Problem, becuase die Abfrage wird früher als erwartet ausgeführt. Jetzt muss ich es so etwas wie ein IQueryable<T>
ändern:
//Repository<User> class
public TableQuery<User> List(where, orderby, topN parameters and etc)
{
//query and return
}
TableQuery<T>
Teil des SQLite-Treiber ist, die fast gleich zu IQueryable<T>
in EF, das eine Abfrage liefert und nicht direkt ausführen lassen. Aber jetzt ist das Problem: in UserManager.cs
, es weiß nicht, was ist ein TableQuery<T>
, muss ich neue Referenz hinzufügen und Namespaces wie using SQLite.Query
im Business-Schicht-Projekt importieren. Es bringt wirklich schlechtes Codegefühl. Warum sollte meine Business-Schicht die Details der Datenbank kennen? Warum sollte die Business-Schicht wissen, was SQLite ist? Was ist das richtige Design dann?
Könnten Sie nicht „nur“ fügen Sie eine neue Ebene von Abstraktionen (Schnittstellen) zwischen der Business-Schicht und Datenzugriffsschicht? Ja, das würde eine neue Menge von Objekten erfordern, die die gleichen Daten in der Business-Schicht repräsentieren, und Mapping zwischen diesen und denen in der DA-Ebene - gewissermaßen Code-Duplikation -, aber es sollte Ihnen einen saubereren Schnitt zwischen den Layern geben Ich verstehe deine Situation richtig. – Kjartan
Ich stimme @Kjartan, was Sie wirklich wollten, ist IQueryable, es ist eine Schande SQLite haben keine, es lohnt sich, eine andere Schichten zu schaffen, um den richtigen Typ zu übertragen. –
ivenxu
@Kjartan @ivenxu: Ich habe nicht gesagt 'TableQuery' ist falsch, noch 'IQueryable ' ist korrekt. Auch habe ich eine neue Übertragungsschnittstelle hinzugefügt, wie 'IQuery ', es ist immer noch * Basis auf * 'TableQuery ', und wenn ich 'IQuery ' in meiner Business-Schicht verwende, ist alles gleich. Es sieht nur * nicht mit SQLite zusammen, aber tatsächlich trägt es eine Maske. –