ADO.net без написания SQL (особенно ГДЕ) - PullRequest
1 голос
/ 03 марта 2009

У меня есть идея, что использование SQL VIEWS для абстрагирования простых вычислений в базе данных (таких как подсчет отношения) достаточно, и вам не нужны процедуры (== процедурный код)

Простой sql view + a , где предложение >> хранимая процедура с параметрами иногда

При изложении этого я придумал способ получения данных таблицы / представления без написания SQL и без предложения where.

Но, к моему удивлению, в ADO.NET 2.0 или более поздних версиях, похоже, нет способа сделать это.

Позвольте мне рассказать вам, что я пытался:

  • SqlDataAdapter + SqlCommandBuilder по-прежнему требует, чтобы вы написали «SELECT ... FROM» и WHERE CLAUSE в строках (плюс, если вы поместите «где», вы не будете часто использовать Обновление / Вставить / DeleteCommand)

  • Типизированные наборы данных позволяют вам только получать _entire DataTable_s и затем применять к ним фильтры. Фильтры - это строки, без экранирования ... (необходимо удвоить одинарную кавычку!)

  • SQL для сущностей выглядел многообещающе, но они, похоже, ограничиваются MSSQL, генерируют раздутые запросы SQL, генерируют целый новый стек DAO (помимо существующих классов доменной модели), требуют .net 3.5+ для всего этого и т. д. (то есть для меня все это недостатки)

Другие ORM имеют те же проблемы, что и SQL для сущностей.

Мне нужен строгий тип доступа к таблицам базы данных / просмотров , которые:

  • не поставляется с другим набором DAO (K.I.S.S)
  • позволяет запрашивать таблицу без записи "SELECTs" в строках (строгого типа)
  • позволяет фильтровать ( WHERE ) таблицу с правильно экранированными параметрами (и без предварительного извлечения всех данных)
  • может позже выпускать обновления / вставки / удаления

Я довольно новичок в .Net, но не глуп: это существует?

Спасибо.

Ответы [ 11 ]

4 голосов
/ 15 июля 2009
2 голосов
/ 21 июля 2009

Subsonic имеет довольно легкий инструмент запросов , который можно использовать для прямого запроса к базе данных с помощью объекта Query, который абстрагирует SQL. При желании вы также можете использовать его средство генерации кода для сопоставления таблиц базы данных с POCO или для создания строго типизированной схемы (для имен столбцов / таблиц и т. Д.).

2 голосов
/ 15 июля 2009

Я действительно не верю, что то, что вы хотите сделать, достижимо без использования какого-либо ORM или специализированного DSL с компилятором, который каким-то образом знает о вашей схеме базы данных, информации о типе / столбце, и т.д.

Примите во внимание, что C # является языком общего назначения, и его компилятор совершенно не знает о ваших типах баз данных, поэтому вы не можете связать их без использования некоторого уровня абстракции, который обычно включает в себя специальные SQL-запросы (строки), NHibernate или аналогичные файлы сопоставления (больше строк) и / или DAO.

1 голос
/ 16 июля 2009

Недавно я написал запрос 'framework' для генерации SQL-выражений where.

Основным компонентом является класс BaseQueryArgs с функцией ToWhereClause (), которая использует отражение для преобразования свойств в строковые секции. Это необходимо для обработки экранирования и правильного форматирования значений.

Любой класс, унаследованный от BaseQueryArgs, просто должен объявить открытые свойства, и вы получите строго типизированный объект запроса. Для необязательных свойств вы делаете значение nullable (ref ref или Nullable <>), а генератор SQL отфильтровывает нулевые значения.

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

  • имя пользовательского столбца, которое отличается от имени свойства
  • обработка пользовательских значений (например, значение даты, используемое в качестве тестового выражения BETWEEN)

Это можно использовать для создания запросов со строго типизированным объектом запроса, например:

MyCustomQueryArgs args = new MyCustomQueryArgs
{
    ProductFamilyID = 17,
    Region = Regions.Northwest,
    Active = true
};

List<Product> product = QueryProcessor.GetProductsWhere(args);

GetProductsWhere (), очевидно, вызовет некоторый метод данных, который обращается к представлению сгенерированным SQL.

У меня нет решения для обновлений / удалений, но не сложно написать метод, который преобразует экземпляр объекта в оператор SQL, используя переключатель или атрибут для определения имени таблицы.

Это очень просто, но это дает вам свободу настраивать его под ваши нужды и не включает в себя много тяжелых ORM / DAO-упаковок.

1 голос
/ 16 июля 2009

Если вы используете строго типизированные наборы данных, вы можете создавать параметризованные запросы в редакторе Visual Studio, добавляя идентификаторы с префиксом @ в запросе. Создайте файл DataSet XSD в Visual Studio и создайте новую таблицу с именем Products, а затем добавьте в нее новый запрос.

Например:

select * from Products where Category = @category;

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

1 голос
/ 15 июля 2009

Я бы предположил, что вы смотрели на LINQ и ADO.Net Data Services , и они не отвечают некоторым вашим требованиям?

Собственный ADO.Net является поставщиком базы данных, и поэтому он обеспечивает прямой интерфейс SQL с основными источниками данных. Существуют различные решения на основе CRUB, которые в различной степени имитируют то, что вы предлагаете.

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

На самом деле не могу поверить, что я забыл добавить ADO.Net Entity Framework , который используется ADO.Net Data Services среди других. Существует также поставщик LINQ to Entities.

1 голос
/ 15 июля 2009

Я сделал что-то подобное с хранимой процедурой один раз. По сути, я хотел указать любую перестановку полей для сопоставления в моем предложении WHERE, но я не хотел писать 100 sprocs с немного другими списками параметров и операторами where.

Итак, я сделал что-то вроде этого:

CREATE PROCEDURE [GetSimpleCustomers]
(
@ID varchar(50) = null,
@Name varchar(50) = null,
@IsActive  bit = null,
@Address1 varchar(50) = null,
@Address2 varchar(50) = null,
@City varchar(50) = null,
@State varchar(50) = null,
@Zip varchar(50) = null
)
AS

SELECT ID, Name, IsActive, Address1, Address2, City, State, Zip
FROM SimpleCustomerExample
WHERE (ID = @ID OR @ID is NULL)
AND (Name = @Name OR @Name is NULL)
AND (IsActive = @IsActive or @IsActive is NULL)
AND (Address1= @Address1 or @Address1 is NULL)
AND (Address2= @Address2 or @Address2 is NULL)
AND (City= @City or @City is NULL)
AND (State= @State or @State is NULL)
AND (Zip= @Zip or @Zip is NULL)

Это позволит вам вызывать sproc в вашем коде и передавать только те параметры, по которым вы хотите выполнить фильтрацию, а остальные не будут учитываться, если вы оставите их пустыми.

Итак, вы можете сделать что-то вроде

public List<SimpleCustomer> GetAllCustomersFromOhio()
{
    List<SimpleCustomer> list = new List<SimpleCustomer>();
    using (SqlCommand cmd = new SqlCommand(blah blah))
    {
        cmd.Parameters.AddWithValue("State", "Ohio");//or "OH" depending on your convention
        using(IDataReader oDR = cmd.ExecuteReader())
        {
             //hydrate your list of SimpleCustomers from the record set.
        }
    }
    return list;
}

EDIT: В ответ на комментарий: Вы можете достаточно легко изменить GetSimpleCustomers на DeleteSimpleCustomers, изменив

SELECT <columns> FROM SimpleCustomers

до

DELETE FROM SimpleCustomers 

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

1 голос
/ 03 марта 2009

Если вы не хотите писать предложение WHERE, одним из способов является использование объекта Filter и добавление необходимых условий. Например:

        var sc = new Filter();
        sc.Add("Contacttitle", "Sales Agent");
        sc.Add("city", "london", Logical.Or);
        var customers = D2Bk.Fetch(sc, new Customers());

Но вы не хотите использовать DAO (клиенты выше), поэтому вам нужно написать оператор SQL и указать предложение where:

        DataSet ds = D2Bk.Fetch("SELECT * FROM Customers WHERE Contacttitle=@PAR1 OR City=@PAR2", "Sales Agent", "london");
0 голосов
/ 20 июля 2009

Я использую Аннотация данных для своих проектов.

0 голосов
/ 19 июля 2009

Я использовал XPO в нескольких проектах, и в их новой версии улучшена поддержка запросов.

http://www.devexpress.com/Products/NET/ORM/

Реализация, как и все они, не лишена недостатков.

...