Je commencerai par dire que, au cours de quelques projets, j'ai implémenté ceci de deux manières différentes, mais je n'ai jamais été satisfait des résultats.Recherche de pointeurs sur une couche d'abstraction de base de données
NOTE: Je fais pas avoir un intérêt à utiliser ORMS!
Un fond
J'ai travaillé sur de nombreux projets qui ont requis une base de données abstraction couches pour plusieurs plates-formes. À l'époque de l'ASP/VBScript classique, nous avions un ensemble de fonctions qui encapsulait le texte SQL pour nettoyer les données, puis construisait la chaîne appropriée pour le fournisseur (SQL Server, MSSQL, Oracle, DB2, etc.). Il y a quelques années, j'ai écrit un DAL qui remplaçait tous ces trucs de ficelles compliquées par des objets réels. L'idée était simple, vous avez dérivé une classe de base de données à partir d'une classe de base de données abstraite pour gérer l'ouverture/fermeture et l'exécution des choses en fonction du fournisseur .NET. On a également fait Insert
, Select
, Update
objets qui ont également travaillé de manière appropriée pour le fournisseur. À vrai dire, même si cela fonctionnait et que le logiciel pouvait fonctionner avec n'importe quelle base de données à travers des objets, le programmeur n'a jamais eu à toucher à SQL; c'était lourd. L'introduction d'une nouvelle plateforme de base de données a pris du temps pour créer tous les objets.
Exemple de code:
DB.Database db = DatabasePool.Get();
try
{
DB.Select select = db.NewSelect("_people"); // MSSQL/Oracle/DB2, doesn't matter
select.Add("_id");
select.Add("_people_name");
select.Where.AndClause("_people_name", DB.Operator.Like, "bob");
DB.Results results = select.ExecuteToCollection();
// here, Select is "tailored" to the right DB provider and returns the correct
// sql.
}
finally
{
DatabasePool.Release();
}
La prochaine version améliorée de ce peu. Au lieu d'avoir une classe de base de données abstraite et un tas d'objets abstraits pour représenter les opérations, il y avait un ensemble d'objets concrets. Les fournisseurs ont ensuite fourni un délégué pour chaque type. Convertir des objets en SQL était un simple cas de le lancer à un Dictionary<Type, Delegate>
et le fournisseur a su convertir cet objet particulier (ou en fait, le type intégral) en SQL, effectuant le nettoyage des données en même temps. Tout était bon, et je me suis amélioré accesseurs aux objets:
DB.Database db = DatabasePool.Get();
try
{
DB.Select select = new Select(db); // now a sealed, concrete object
select.Add("_id").Add("_people_name");
select.Where.And("_people_name", DB.Op.Like, "bob");
DB.Results results = select.Query();
// much better now. Select is a sealed object. The Database class has a bunch of
// delegates that convert any type (including Select, Delete, int, decimal) to
// appropriate SQL. Much less work implementing different providers.
}
finally
{
DatabasePool.Release();
}
maintenant
J'ai l'occasion maintenant, de faire à nouveau ce (et le projet à temps pour le faire). Je suppose que ma question est, est-ce une bonne façon de gérer différents fournisseurs encapsulant des opérations de base de données dans des objets? Alors que les délégués fonctionnent très bien:
1) Il est facile d'écrire un générateur pour Column
, Select
, Delete
, int
, NULL
, etcetera, mais lors de la construction WHERE
clauses, je me suis retrouvé avec un tas de petits objets atomiques qui ont fait « pièces ' de choses.
2) Alors que les différentes versions de SQL ont des différences subtiles, la majorité est la même. La classe base-database a fourni des valeurs par défaut acceptables pour à peu près tous les objets, et différents fournisseurs ont simplement remplacé ces délégués. Mais je n'ai pas vu cela très "clair" pour le programmeur. Il n'était pas clair lequel était géré par quelle couche de code.
Y a-t-il un meilleur moyen? Je suis heureux avec le concept des objets remplaçant l'écriture de n'importe quel SQL que ce soit. Ils facilitent la création dynamique d'instructions SQL, avec un nettoyage et une conversion de type appropriée du type de base de données au type .NET (par exemple, je n'ai jamais à traiter avec des types de base de données en dehors des objets de base de données.Je reçois toujours un DateTime, System.UInt32, un bool, etc).
Merci pour cela, je vais y jeter un coup d'oeil. Comment cela gérerait-il également l'encapsulation de la création/modification de tables/colonnes, de suppressions, d'insertions et de mises à jour? Le DAL J'ai fait des objets fournis pour faire toutes ces choses sans se soucier de la syntaxe sous-jacente. –
LINQ ne peut représenter que la partie Requête de ces instructions, vous devez donc définir votre propre mécanisme pour interpréter la requête dans le contexte d'un DELETE ou UPDATE, par exemple (la construction de requête est toujours très utile pour spécifier ce que DELETE et qui enregistre à UPDATE.) –
Salut Dan, j'ai fait un peu de creuser et je pense que LINQ pourrait bien satisfaire les parties de mes objets et qu'intégrer les deux peut être le chemin à parcourir ici. Je suppose que ma dernière question à ce sujet est, étant donné les requêtes LINQ que je vois posté tout le temps ici, comment est-ce actuellement converti en SQL et existe-t-il déjà une couche d'abstraction pour traiter avec différents fournisseurs? Merci! :) –