Вопрос

В настоящее время я разрабатываю приложение query builder, по сути, простой графический интерфейс, который должен позволять пользователям, не разбирающимся в SQL, определять различные запросы к базе данных (joins, SELECT, INSERT, UPDATE, DELETE).Я буду использовать .NET 3.5.Мое приложение должно поддерживать несколько баз данных, оно должно работать с MS-SQL Server, MySQL и Oracle, поэтому я был бы признателен за любые подсказки или ссылки на соответствующую лекцию по как создать независимый от поставщика DAL.

Пользователь выберет сервер базы данных, базу данных на текущем сервере, предоставит учетные данные для подключения, выберет различные таблицы, определит запросы (используя ряд полей со списком) и, наконец, выполнит запросы, если они допустимы.Конечно, в DAL я действительно хочу иметь методы для каждого поставщика БД.Я думаю о чем-то похожем на фабричный шаблон.

Примечание:Это простой школьный проект, поэтому меня не интересует безопасность или производительность результирующих запросов.

Обновить: После еще некоторых исследований и с учетом очень ценного вклада, который вы предоставили, я решил использовать DbProviderFactory.ORM был бы интересен, но поскольку мне просто нужен анализатор запросов / конструктор, я не вижу смысла его использовать.Итак, я был бы признателен, если бы вы указали мне на подробное руководство по использованию DbProviderFactory и связанные с ними классы.

Это было полезно?

Решение

Я рекомендую использовать System.Data.Common.DbProviderFactories класс для создания универсальных ADO.NET классов.

Когда вы найдете больше поставщиков .NET для баз данных, которые хотите поддерживать, просто поместите DLL-файл поставщика в путь к приложению и добавьте ссылку на DbProviderFactory поставщика услуг в app.config файл.Вы можете попросить пользователя выбрать поставщика для использования.

Вот статья MSDN по теме под названием Получение DbProviderFactory (ADO.NET)

Я использовал этот подход раньше и смог поддерживать MSSQL и SQLite в одном проекте с незначительным изменением конфигурации.

Хотя не уверен, будет ли это работать так же хорошо для приложения query builder…

Другие советы

Я должен сказать, что визуальное редактирование достаточно сложного запроса - это очень громоздкий.А позволять пользователям вставлять / удалять данные с помощью visual designer - это верный способ выстрелить себе в ногу.Уменьшенная версия Management Studio, знание базового SQL плюс ограниченный пользователь сервера сделают работу намного лучше.

Если вы все еще склонны разрабатывать это приложение, вам понадобится NHibernate.Более точно, Запросы по критериям выполнят свою работу, так как они отображают довольно близко к тому, что вам нужно.

Вы можете быть удивлены, но очень простой, независимый от поставщика DAL может быть достигнут с помощью простого старого DataSet и DataTable.

Я думаю ADO.NET Entity Framework (доступна начиная с .NET 3.5 SP1) - отличный выбор, поскольку она в значительной степени абстрагирует SQL, зависящий от базы данных, с помощью языка entity SQL.

Почти любой ORM (объектно-реляционный картограф) будет знать, как взаимодействовать с различными типами баз данных.

Что касается предоставления пользователям возможности создавать свои собственные запросы:вам нужно быть с этим очень осторожным.Дело не столько в том, что пользователи могут создавать вредоносные запросы (хотя это может быть проблемой), сколько в том, что это случайность.Удивительно просто написать запрос, который будет использовать все доступные ресурсы сервера и создаст эффективный отказ в обслуживании для вашей базы данных.

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

public interface IModelIdentifier<T> where T : class 
{
    /// <summary>
    /// A string representation of the domain the model originated from.
    /// </summary>
    string Origin { get; }

    /// <summary>
    /// The model instance identifier for the model object that this 
    /// <see cref="IModelIdentifier{T}"/> refers to.  Typically, this 
    /// is a database key, file name, or some other unique identifier.
    /// <typeparam name="KeyDataType">The expected data type of the 
    /// identifier.</typeparam>
    /// </summary>
    KeyDataType GetKey<KeyDataType>();

    /// <summary>
    /// Performs an equality check on the two model identifiers and 
    /// returns <c>true</c> if they are equal; otherwise <c>false</c> 
    /// is returned.  All implementations must also override the equal operator.
    /// </summary>
    /// <param name="obj">The identifier to compare against.</param>
    /// <returns><c>true</c> if the identifiers are equal; otherwise 
    /// <c>false</c> is returned.</returns>
    bool Equals(IModelIdentifier<T> obj);
}

Ваш уровень бизнес-логики, который, возможно, в прошлом проходил ints как уникальные идентификаторы (например, из столбца идентификаторов в таблице вашей базы данных), теперь передаются как таковые:

    public IPerson RetrievePerson(IModelIdentifier<IPerson> personId)
    {
        /// Retrieval logic here...
    }

Затем ваш уровень данных будет иметь класс, который реализует IModelIdentifier<Person> и заполняет свой внутренний тип данных уникальным идентификатором физической модели.Это изолирует ваш бизнес-уровень от любых изменений, которые могут произойти на уровне данных, таких как замена вашего int идентификаторы ключей с Guids.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top