Существуют ли ОО-модели для генерации SQL? - PullRequest
1 голос
/ 02 февраля 2009

Мне было интересно, существует ли какой-либо код, который позволяет представлять SQL в виде некоторого дерева объектов, которое можно собрать, изменить и затем, наконец, преобразовать в допустимый SQL?

С моей головы это может выглядеть примерно так ...

var stmnt = new Statement();
stmnt
  .AddMaster("Customer")
  .Show("Firstname, "Lastname")
  .AddJoin("Address", "ID", "CustomerID")
  .Show("Street", "City");
stmnt.WhereStatement()
  .AddParameter("Address.City", Op.Equal);

string sql = stmnt.Generate();
// select a.FirstName, a.LastName, b.Street, b.City
// from Customer a
// join Address b on b.CustomerID = a.ID
// where b.City = :p1

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

UPDATE:

Мне известно о многочисленных возможностях использования технологий ORM для получения моих результатов из БД, но я выбрал модель для самого SQL. Я знаю, что уровень абстракции довольно низок, но он может позволить создать ситуацию, когда несколько соавторов могут работать над оператором SQL (несколько соединений, несколько мест), который затем может быть «визуализирован» в конце фазы сборки.

Ответы [ 7 ]

5 голосов
/ 02 февраля 2009

Hibernate имеет собственный язык запросов Hibernate (HQL), который представляет SQL-подобные конструкции в виде объектов.

2 голосов
/ 03 февраля 2009

Пакет Python SQLAlchemy имеет слой ORM, но также имеет слой генерации SQL.

[Я понимаю, что вы пометили этот пост c # и .net, но я подумал, что вы хотели бы посмотреть, что еще там есть]

Вот пример кода:

from sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKey
from sqlalchemy.sql import select

metadata = MetaData()

# Make a basic customer table.
Customer = Table('Customer',
                 metadata,
                 Column('ID', Integer, primary_key=True),
                 Column('FirstName', String),
                 Column('LastName', String))

# Make a basic address table
Address = Table('Address',
                metadata,
                Column('ID', Integer, primary_key=True),
                Column('City', String),
                Column('Street', String),
                Column('CustomerID', None, ForeignKey('Customer.ID')))


# Generate some sql
stmt = select([Customer.c.FirstName,
               Customer.c.LastName,
               Address.c.Street,
               Address.c.City],
              from_obj=Customer.join(Address),
              whereclause=Address.c.City == 'Wellington')

# Display
print stmt
# output:
SELECT "Customer"."FirstName", "Customer"."LastName", "Address"."Street", "Address"."City" 
FROM "Customer" JOIN "Address" ON "Customer"."ID" = "Address"."CustomerID" 
WHERE "Address"."City" = :City_1

# note that SQLAlchemy picked up the join condition from the foreign key.
# you can specify other join conditions if you want.

Как правило, вы выполняете инструкцию, используя SQLAlchemy для подключения к базе данных. Тогда вы можете сделать:

for row in stmt.execute():
    print 'Name:', row.c.FirstName, row.c.LastName, 'City:', row.c.City

Надеюсь, это поможет.

2 голосов
/ 02 февраля 2009

Смотрите выше, и я видел, как несколько программистов шли по этому пути. (И я сказал более чем одному программисту, что видел более одного программиста ..., но обычно они в конечном итоге сами выясняют, насколько хорошо это работает.)

Трудность, которую я вижу, состоит в том, что вы добавляете существенную сложность, не предлагая много способов абстракции. В любом случае вам нужно знать, каким SQL вы будете в конечном итоге.

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

2 голосов
/ 02 февраля 2009

OR-Mapper, например Microsoft LINQ

Вот несколько примеров:

from c in customers
where c.LastName.StartsWith("A")
select c

//

var q = from c in db.Contact
           where c.DateOfBirth.AddYears(35) > DateTime.Now
           orderby c.DateOfBirth descending
           select c;

Некоторые ссылки для начала работы:

1 голос
/ 02 февраля 2009

Вы можете попробовать MetaDb . Есть проделанная работа. Пример запроса http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=metadb&DownloadId=11482

Но если вы можете использовать .NET 3.5, вы можете использовать LINQ.

0 голосов
/ 02 февраля 2009

Если вы все еще используете .NET 2.0 и не перешли на LINQ, я бы создал базовый класс операторов, а затем создал классы, которые допускают использование шаблона декоратора.

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

0 голосов
/ 02 февраля 2009

В .Net Linq делает то, о чем вы говорите.

...