Nous concevons un produit pouvant prendre en charge plusieurs bases de données. Nous faisons quelque chose comme ceci actuellement pour que notre code prend en charge MS SQL ainsi que MySQL:
namespace Handlers { public class BaseHandler { protected string connectionString; protected string providerName; protected BaseHandler() { connectionString = ApplicationConstants.DatabaseVariables.GetConnectionString(); providerName = ApplicationConstants.DatabaseVariables.GetProviderName(); } } } namespace Constants { internal class ApplicationConstants { public class DatabaseVariables { public static readonly string SqlServerProvider = "System.Data.SqlClient"; public static readonly string MySqlProvider = "MySql.Data.MySqlClient"; public static string GetConnectionString() { return ConfigurationManager.ConnectionStrings["CONNECTION_STRING"].ConnectionString; } public static string GetProviderName() { return ConfigurationManager.ConnectionStrings["CONNECTION_STRING"].ProviderName; } } } } namespace Handlers { internal class InfoHandler : BaseHandler { public InfoHandler() : base() { } public void Insert(InfoModel infoModel) { CommonUtilities commonUtilities = new CommonUtilities(); string cmdInsert = InfoQueryHelper.InsertQuery(providerName); DbCommand cmd = null; try { DbProviderFactory provider = DbProviderFactories.GetFactory(providerName); DbConnection con = LicDbConnectionScope.Current.GetOpenConnection(provider, connectionString); cmd = commonUtilities.GetCommand(provider, con, cmdInsert); commonUtilities.PrepareCommand(cmd, infoModel.AccessKey, "paramAccessKey", DbType.String, false, provider, providerName); commonUtilities.PrepareCommand(cmd, infoModel.AccessValue, "paramAccessValue", DbType.String, false, provider, providerName); cmd.ExecuteNonQuery(); } catch (SqlException dbException) { //-2146232060 for MS SQL Server //-2147467259 for MY SQL Server /*Check if Sql server instance is running or not*/ if (dbException.ErrorCode == -2146232060 || dbException.ErrorCode == -2147467259) { throw new BusinessException("ER0008"); } else { throw new BusinessException("GENERIC_EXCEPTION_ERROR"); } } catch (Exception generalException) { throw generalException; } finally { cmd.Dispose(); } } } } namespace QueryHelpers { internal class InfoQueryHelper { public static string InsertQuery(string providerName) { if (providerName == ApplicationConstants.DatabaseVariables.SqlServerProvider) { return @"INSERT INTO table1 (ACCESS_KEY ,ACCESS_VALUE) VALUES (@paramAccessKey ,@paramAccessValue) "; } else if (providerName == ApplicationConstants.DatabaseVariables.MySqlProvider) { return @"INSERT INTO table1 (ACCESS_KEY ,ACCESS_VALUE) VALUES (?paramAccessKey ,?paramAccessValue) "; } else { return string.Empty; } } } }
10 Réponses :
Il existe des couches de cartographie relatives à des objets qui prend en charge plusieurs technologies de base de données, telles que espaces d'entité . P>
Quoi que vous fassiez, NE PAS B> Écrivez votre propre code de cartographie. Son déjà été fait auparavant, et c'est probablement fait un million de fois meilleur que tout ce que vous pouviez écrire à la main. P>
Sans aucun doute, vous devriez utiliser Nibernate . C'est un mappeur d'objet-relation qui rend l'accès à la base de données transparent: vous définissez un ensemble de classes DAL qui représentent chaque tableau dans votre base de données et que vous utilisez les fournisseurs NHibernate pour effectuer des requêtes sur votre base de données. NHibernate générera dynamiquement le SQL requis pour interroger la base de données et peupler vos objets DAL. P>
La bonne chose à propos de NHibernate est qu'elle génère SQL en fonction de tout ce que vous avez spécifié dans le fichier de configuration. Hors de la boîte, il prend en charge SQL Server, Oracle, MySQL, Firebird, Postgres et Quelques autres bases de données a>. p>
Depuis doute
Une approche de ce problème consiste à concevoir votre application pour travailler entièrement avec des jeux de données déconnectés et à écrire un composant d'accès aux données qui gère la récupération des données des différentes marques de base de données que vous appuierez, ainsi que des modifications persistantes apportées aux données de données. Par votre demande, répondez aux bases de données d'origine. P>
Avantages: Les jeux de données dans .NET sont bien écrits, faciles à utiliser et puissants et font un excellent travail de fourniture de méthodes et d'outils pour travailler avec des données de table. P>
Inconvénients: Cette méthode peut être problématique si votre application doit fonctionner avec des ensembles de données extrêmement volumineux sur le côté client. P>
Qu'est-ce qui est toujours bon dans de tels cas consiste à créer une architecture en couches, où toutes les formes liées à la DB sont juste dans la couche d'accès aux données. Ensuite, vous pourriez avoir différentes implémentations de votre couche DAO, une pour Oracle, SQL Server, etc. p>
Vous devez séparer la couche d'entreprise de la couche DAO avec des interfaces, de sorte que votre couche d'entreprise utilise simplement pour accéder à la couche DAO. Donc, vous pouvez perfectionner parfaitement la mise en œuvre de la couche de sous-couche de la couche DAO pour fonctionner sur un DB Oracle ou quel que soit le système que vous aimez. P>
Une autre bonne suggestion est de jeter un coup d'œil aux mappeurs relationnels comme Scott déjà suggéré. Je jetterai un coup d'oeil au cadre de NHibernate ou d'entité. P>
En ce moment, l'entité d'entité de Microsoft a quelques courts-livres, certains d'entre eux qui peuvent être des casseroles, en fonction de l'architecture prévue de l'application. P>
De ce que j'ai vu et lu sur V2, qui sera expédié avec .NET 4, je pense que cela méritera certainement d'être examiné. P>
Beaucoup de gens ont suggéré un cadre de cartographie O / R telle que NHibernate. C'est une approche assez raisonnable à moins que vous ne vouliez pas utiliser de mappeuse O / R pour une raison quelconque. Quelque chose comme Nhibernate vous obtiendra probablement 95% + de la manière dont vous devrez peut-être écrire un SQL personnalisé. Ne paniquez pas si c'est le cas; Vous pouvez toujours faire une solution ad-hoc pour le reste. P>
Dans ce cas, prenez les bits qui ont besoin du SQL personnalisé et de les séparer dans un module de plugin spécifique à la plate-forme. Écrivez des plug-ins Oracle, MySQL, SQL Server (etc.) si nécessaire pour les différentes plates-formes de base de données que vous souhaitez prendre en charge. p>
ado.net le rend assez facile à emballer des Sprates, de sorte que vous puissiez peut-être déplacer la couche dépendante de la plate-forme dans certaines procédures stockées, en présentant une API de consitement plus ou moins au niveau du niveau moyen. Il existe toujours des dépendances de la plate-forme (telles que le préfixe '@' sur les noms de variable SQL Server), vous devez donc créer un mécanisme générique de wrapper SproC (qui n'est pas tout ce qui est difficile). p>
Avec toute chance, les opérations spécifiques que vous ont besoin em> de sortir de cette manière seront assez petites du nombre de personnes afin que la quantité de travail à maintenir les plugins soit limitée. P>
Si vous devez le coder vous-même et n'utilisez pas un produit qui fournit un accès unifié, rappelez-vous que des objets tels que SQLDataAnPortter et OracleDataAdapter hériter de la DBDataDapter commun (au moins dans les versions ultérieures du temps d'exécution). Si vous lancez à DBDataAdapter, vous pouvez écrire du code qui fonctionnera avec les deux bases de données dans les endroits où vous feriez la même chose pour les deux bases de données. Certains de votre code sembleront un peu comme celui-ci:
DbDataAdapter adapter = GetOracleDataAdapter() as DbDataAdapter;
Si vous avez besoin d'une cartographie des entrées de base de données sur des objets, je vous suggère d'aller avec la solution d'autres déjà suggérées: NHibernate. Si cela ressemble à une overkill pour votre application et que vous souhaitez aller avec l'approche ADO.net et n'avez pas besoin de O / RM-Soultion, vous devriez avoir un coup d'oeil sur ce que les gars Spring.net ont fait et apprennent sur le ADO.net Fournisseur Abstraction. P>
Pour votre besoin actuel, je suis d'accord avec NHibernate ...
Voulez-vous simplement souligner quelque chose avec votre hiérarchie de classe ... p>
Vous ferez mieux d'utiliser l'interface P>
Comme (juste vérifier le doc ou Internet pour la syntaxe exacte) p> puis dans votre code, vous pouvez utiliser l'interface p>
Je vous suggère de casser le code dans différents
code> pré> pour vous faciliter la lecture. Comme c'est le cas, il y a beaucoup de code débordement de la marge droite et il n'y a qu'une seule barre de défilement horizontale vers le bas vers la fin du code.