C # DB Wrapper для поддержки нескольких баз данных - PullRequest
1 голос
/ 30 октября 2011

В настоящее время я создаю приложение на C #, которое поддерживает базы данных MySQL и MSSQL. У меня проблема с моей оберткой. Мой код работает для MySQL, но у меня возникают проблемы с его изменением для поддержки нескольких баз данных.

Если вы посмотрите на урезанную версию моего кода, вы увидите, что у меня есть объект dbConn типа DBMySQL, что хорошо, если я хочу только поддержку MySQL. Мне нужно изменить DBMySQL, чтобы он был чем-то общим, чтобы я мог запустить dbConn = new DBMySQL (...) и dbConn = DBMSSQL (...), а затем просто вызвать dbConn.SomeMethod () и заставить его работать с соответствующей базой данных , Я бы предпочел сохранить эту настройку в максимально возможной степени, поскольку в моих классах DBMySQL и DBMSSQL есть другие вещи для массовой вставки в базы данных и проверки конкретных ошибок.

Я думал / пытался объявить что-то вроде Object dbConn, затем манипулировал этим, но это не так хорошо. Затем я попытался использовать класс объектов enum, но у меня тоже были проблемы с этим. Я знаю, что есть много сторонних библиотек, которые делают все это, но я бы предпочел использовать свой собственный код.

У кого-нибудь есть предложения, как мне изменить мой DBWrapper для решения этой проблемы?

//WRAPPER CLASS THAT CALLS DBMySQL, ISSUE IS I NOW NEED TO SUPPORT 
//DBMSSQL as well, not just DBMySQL
class DBWrapper
{
    DBMySQL dbConn;

    public DBWrapper(...,string type)
    {
        if(type.Equals("MySQL")
        {
            dbConn = new DBMySQL(...);
        }
        //NEED TO REWORK TO SUPPORT THIS BELOW!!
        else if(type.Equals("MSSQL")
        {
            //NEED TO MODIFY TO SUPPORT MSSQL
            //ISSUE IS DbConn is of type DBMySQL
            //SO I CANNOT GO
            // DbConn = new DBMSSQL(...);
            // any ideas?
        }   
    }

    public void setQuery(string myquery)
    {
            dbConn.setQuery(myquery);
    }
}

class DBMySQL
{
    public string dbinfo;
    string query;

    public DBMySQL(...)
    {
        dbinfo = ...;

    }

    public void setQuery(...)
    {
        query = myquery;
    }
}

//NEED TO RE-WORK WRAPPER TO SUPPORT THIS
class DBMSSQL
{
    public string dbinfo;
    string query;

    public DBMSSQL(...)
    {
        dbinfo = ...;

    }

    public void setQuery(...)
    {
        query = myquery;
    }
}

На данный момент я был бы признателен за любую помощь, поэтому, если вы просматриваете этот пост и у вас есть идея, пожалуйста, дайте мне знать, поскольку я уже потратил на это целый день.

Ответы [ 6 ]

6 голосов
/ 30 октября 2011

Вам нужно создать интерфейс, который бы описывал, что вы хотите, чтобы ваши классы доступа к данным делали.

Например, из вашего образца

public interface IDBAccess
{
     void setQuery(...);
}

public class DBMySQL : IDBAccess
{
    public string dbinfo;
    string query;

    public DBMySQL(...)
    {
        dbinfo = ...;

    }

    public void setQuery(...)
    {
        query = myquery;
    }
}

public class DBMSSQL : IDBAccess
{
    public string dbinfo;
    string query;

    public DBMSSQL(...)
    {
        dbinfo = ...;

    }

    public void setQuery(...)
    {
        query = myquery;
    }
}

На этом этапе вы сможетесделайте это:

IDBAccess dbConn;
dbConn = new DBMySQL();
dbConn = new DBMSSQL();

Учитывая, что вы новичок в этом, не стоит предлагать вам взглянуть на NHibernate или Castle ActiveRecord и Замок Виндзор .Но имейте это в виду на будущее.

2 голосов
/ 30 октября 2011

Есть ли конкретная причина, по которой вы хотите переопределить слой базы данных в C #?Вы смотрели на использование сказать; Entity Framework , NHibernate или любой другой .NET ORM?Это позволило бы легко обернуть весь доступ к данным, не беспокоясь о деталях реализации.Кроме того, они предоставляют другие преимущества, такие как сопоставление таблиц с классами для вас (т. Е. Они заполняют ваши классы на основе того, что находится в ваших таблицах и наоборот), кэширование и различные другие функции.

В качестве альтернативы, если вы действительно хотите создать свой собственный, то вам нужно объявить интерфейс, сделать так, чтобы все ваши подключения к базе данных наследовали от этого интерфейса, и сохранить экземпляры соединений в свойстве типа интерфейса.Т.е.:

public interface IDatabaseConnection
{
    void setQuery(string myQuery);
}

public class DBWrapper
{
    private IDatabaseConnection Connection { get; set; } 

    public DBWrapper(string type)
    {
        if(type == "MySql")
            Connection = new DBMySQL();
        else if(type == "MsSql")
            Connection = new DBMSSQL();
    }
}

public class DBMySQL : IDatabaseConnection
{
    ...
}

public class DBMSSQL : IDatabaseConnection
{
    ...
}
2 голосов
/ 30 октября 2011

Вы не должны создавать один большой класс, который обрабатывает обе базы данных.Вам следует создать общий интерфейс для вашей оболочки IDBWrapper, а затем создать отдельную реализацию для каждой базы данных.

После этого вы можете создать некоторую логику, которая выберет правильную реализацию для вас.Вы не хотите писать что-то подобное каждый раз, когда вам нужна оболочка:

IDBWrapper db = (useMySQL ? new MySqlDBWrapper(...) : new MsSqlDBWrapper(...));

Есть несколько вариантов.Вы можете использовать абстрактную фабрику, но на самом деле все, что абстрагируется от создания оболочки базы данных, будет работать.

1 голос
/ 30 октября 2011

В ADO.NET все классы соединений наследуются от System.Data.Common.DbConnection , так что на самом деле вы хотите встроить в .NET - все, что вам нужно сделать, это сохранить соединение вDbConnection вместо SqlConnection / MySqlConnection и используйте классы в System.Data.Common вместо классов в System.Data.Sql/MySql/.

Ваша главная проблема здесьНа мой взгляд, нет никакого реального стандарта SQL - кроме простого выбора и вставки, вам потребуется другой синтаксис для запросов SqlServer и MySql.Чтобы решить эту проблему, вам нужно либо использовать Linq to SQL - что является большой работой, если вы не хотите зависеть от библиотек - или, если вы хотите, чтобы ваша оболочка выполняла специфические операции - вы можете иметь словарь для каждой базы данных, в котором хранятся готовые к String.Format шаблоны запросов этих операций и применяться во время выполнения в методах-обертках, выполняющих эти операции.

1 голос
/ 30 октября 2011

Вы также можете взглянуть на шаблон общего репозитория и ORM для этих БД.

0 голосов
/ 30 октября 2011

Один быстрый способ взломать, который я могу придумать, - создать один огромный класс с необходимой поддержкой для обоих и на основе того, что выбрал пользователь, использовать соответствующие объекты и классы.Кроме того, вы можете создать несколько классов, по одному для каждого из ваших источников данных, а затем создать один класс посадки, который будет перенаправлять на правильный класс поставщика источника данных на основе того, что выбрал пользователь.Не очень красиво, но тот, который может сработать ...

...