Как сказала моя коллега "мы не специалисты в БД"
Проблема в следующем. Имеется база данных доступ к которой организован через запросы LINQ to SQL. Шеф сказал, что от LINQ он отказываться не хочет, но теперь вместо доступа к таблицам и полям БД надо будет использовать LINQ к Store Procedure. Аргументом к этому служит то, что SQL-серверу не надо будет компилировать запрос каждый раз и это увеличит производительность.
Вопрос в следующем.
На самом деле ли LINQ к Store Procedure сможет улучшить производительность системы?
Здравствуйте, Spender, Вы писали:
S>На самом деле ли LINQ к Store Procedure сможет улучшить производительность системы?
Плюс хранимой процедуры в том, что ее можно "оптимизировать" не трогая оригинальное приложение. в остальном, современные SQL сервера умеют кешировать планы выполнения запросов.
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте, TK, Вы писали:
TK>Плюс хранимой процедуры в том, что ее можно "оптимизировать" не трогая оригинальное приложение. в остальном, современные SQL сервера умеют кешировать планы выполнения запросов.
Оптимизировать никто не будет. Предлагается текущие запросы, сформированные LINQ просто скопировать на сервер и сделать из них хранимые процедуры. Про кэш я сказал. На это мне ответили, что запросов тысячи и что кэш здесь не поможет. Я не силен в этом, но как-то сомневаюсь. Зачем же он тогда нужен, если не поможет. Можете привести аргументы, статьи какие-нибудь. Буду очень признателен
Здравствуйте, Spender, Вы писали:
S>Проблема в следующем. Имеется база данных доступ к которой организован через запросы LINQ to SQL. Шеф сказал, что от LINQ он отказываться не хочет, но теперь вместо доступа к таблицам и полям БД надо будет использовать LINQ к Store Procedure. Аргументом к этому служит то, что SQL-серверу не надо будет компилировать запрос каждый раз и это увеличит производительность.
S>Вопрос в следующем. S>На самом деле ли LINQ к Store Procedure сможет улучшить производительность системы?
Нет, не сможет.
SQL-серверу определяет нужно компилировать запрос или нет полагаясь только на текст запроса. Откуда конкретно этот текст взят (из хранимки или пришел с клиента) ему абсолютно не важно. Важно лишь чтобы текст запроса всегда был одним и тем же. Если вы сможете гарантировать, что sql, генерируемый по LINQ-запросу, будет одним и тем же, то автоматом получите кеширование планов запроса.
Здравствуйте, Lloyd, Вы писали:
L>Нет, не сможет.
... L>Если вы сможете гарантировать, что sql, генерируемый по LINQ-запросу, будет одним и тем же, то автоматом получите кеширование планов запроса.
Запросы будут одинаковые, параметры запроса будут разные. Я так понимаю, это не повлияет на кэш. А где об этом можно почитать, желательно на английском
Здравствуйте, Spender, Вы писали:
L>>Если вы сможете гарантировать, что sql, генерируемый по LINQ-запросу, будет одним и тем же, то автоматом получите кеширование планов запроса.
S>Запросы будут одинаковые, параметры запроса будут разные. Я так понимаю, это не повлияет на кэш. А где об этом можно почитать, желательно на английском
Спасибо большое!!!
А ещё я как-то не нашел в сети сравнения производительности LINQ и Store Procedure. Вернее нашел, один, но там было сказано, что Store Procedure в 3-4 раза "быстрее", имеется ввиду эффективнее. Ссылкой на такие сравнения не раполагаете?
Здравствуйте, Spender, Вы писали:
S>А ещё я как-то не нашел в сети сравнения производительности LINQ и Store Procedure. Вернее нашел, один, но там было сказано, что Store Procedure в 3-4 раза "быстрее", имеется ввиду эффективнее. Ссылкой на такие сравнения не раполагаете?
Нет, таких ссылок нет. Но что мешает самому написать подобные тесты? Вроде ничего сложного не должно быть.
Здравствуйте, Lloyd, Вы писали:
L>Нет, таких ссылок нет. Но что мешает самому написать подобные тесты? Вроде ничего сложного не должно быть.
Опыта c SQL не много. Попробую. Вот сейчас коллегам разослал. Сидят, что-то обсуждают. Смеются. Я по-китайски не очень Сказли шефу пошли. Вот думаю, не уволит за слишком "рьяное" стремление улучшить?
Здравствуйте, Spender, Вы писали:
S>Доброго времени суток, всем!
S>Как сказала моя коллега "мы не специалисты в БД" S>Проблема в следующем. Имеется база данных доступ к которой организован через запросы LINQ to SQL. Шеф сказал, что от LINQ он отказываться не хочет, но теперь вместо доступа к таблицам и полям БД надо будет использовать LINQ к Store Procedure. Аргументом к этому служит то, что SQL-серверу не надо будет компилировать запрос каждый раз и это увеличит производительность.
S>Вопрос в следующем. S>На самом деле ли LINQ к Store Procedure сможет улучшить производительность системы?
производительность системы — да, производительность программистов от этого сильно уменьшится.
Давно я не встречал технических документов, которые были написаны хуже чем этот. Уже несколько лет читаю книги и литературу на английском, но этот текст заставил меня неслабо напрягаться и перечитывать предложения и абзацы по несколько раз.
Здравствуйте, Spender, Вы писали:
S>Оптимизировать никто не будет. Предлагается текущие запросы, сформированные LINQ просто скопировать на сервер и сделать из них хранимые процедуры. Про кэш я сказал. На это мне ответили, что запросов тысячи и что кэш здесь не поможет. Я не силен в этом, но как-то сомневаюсь. Зачем же он тогда нужен, если не поможет. Можете привести аргументы, статьи какие-нибудь. Буду очень признателен
Почитайте тут: http://msdn.microsoft.com/ru-ru/library/ms181055.aspx
В остальном, надо исходить из того, что SQL Server хранит только исходный код хранимых процедур и триггеров. При выполнении хранимой процедуры или триггера в первый раз исходный код компилируется в план выполнения. т.е. разница только в том, где будет хранится "текст" запросов. в случае с хранимыми процедурами (особенно если их тысячи) вы "усложняете" себе поддержку вашего решения.
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте, gandjustas, Вы писали:
S>>На самом деле ли LINQ к Store Procedure сможет улучшить производительность системы? G>производительность системы — да,
Можешь объяснить из-за чего может улучшиться производительность системы?
Здравствуйте, koandrew, Вы писали:
K>Здравствуйте, Lloyd, Вы писали:
L>>Можешь объяснить из-за чего может улучшиться производительность системы?
K>Экономия трафика на пересылку запроса vs пересылку имени хранимки?
Наверное только этим. Ну и еще конечно отсуствие затрат по генерации запроса.
[...]
свои пять копеек...из того небольшого опыта применения linq to sql могу сказать следующее:
linq to sql не панацея от всех болезней, существуют и другие orm системы (например, от DevExpress очень неплох XPO, гораздо дальше ушел от linq to sql),
позволяющие убрать непосредственное общение со скриптами, но общий минус у всех один и тот же — это возможность получения такого плана выполнения,
который и в страшном сне не приснится ну и соотвественно медленные запросы...те вещи, которые являются родными для sql определенного диалекта ну никак не перенести в конструкции c# linq (функции обработки данных, преобразования типов), к тому же, если речь идет о сложной логике обработки данных (скажем, некие предпросчеты, или запросы к распределенным системам, построенным на linked servers) то гораздо выгоднее и компактнее написать такую логику в процедурах и использовать их как методы linq to sql context-а... (уж не говорю о том, что сложно построить linq контекcт, построенный на нескольких базах данных)
мое скромное мнение — linq to sql годится для небольших систем с небольшой нагрузкой аля desktop winforms app,
если же предполагается, что система будет расти, то лучше сразу закладываться на использование процедур...
некоторые могут возразить по поводу оптимизации — мы же можем спрофилировать сгенерированные запросы от linq и произвести их оптимизацию путем оптимизации планов, построения индексов и прочее, но поверьте, когда запрос наподобие указанного ниже уходит на сервер, оптимизировать его становится очень сложно, опять таки, если есть кому оптимизировать такие запросы и работать с базой (есть такие люди dba), то может лучше ему и отдать обязанности по обработке этих данных на стороне сервера — разделение труда и узкая специализация?
var leads = (from lsp in ctx.LeadsSalesReps
join lead in ctx.Leads on lsp.LeadID equals lead.ID
join customer in ctx.Customers on lead.CustomerID equals customer.ID
let leadProvider = lead.LeadProvider
where lead.CustomerID != null &
lsp.CompanyGUID == CurrentCompany.GUID
select new
{
LeadID = lead.ID,
CustomerID = lead.CustomerID,
Name = lead.Customer.FirstName + " " + lead.Customer.LastName,
Source = lead.LeadSource,
LeadRequestDate = lead.LeadRequestDate,
LeadPriority = lead.LeadPriority,
LastActionCompleted = (from phocecall in ctx.PhoneCalls
where phocecall.CustomerID == lead.CustomerID
select new
{
Action = "Made a phone call",
Date = phocecall.CallDate
}
).Union(
(from email in ctx.EMails
where email.CustomerID == lead.CustomerID
select new
{
Action = "Send an email",
Date = email.SentDate
})
).OrderByDescending(d => d.Date).First().Action,
NextActionDate = (from appointment in ctx.Appointments
where appointment.CustomerID == lead.CustomerID &&
appointment.StartDate >= lead.LeadRequestDate &&
appointment.Status.HasValue && appointment.Status.Value != 3 /* completed */select appointment
).OrderBy(a => a.StartDate).First().StartDate,
NextAction = (from appointment in ctx.Appointments
where appointment.CustomerID == lead.CustomerID &&
appointment.StartDate >= lead.LeadRequestDate &&
appointment.Status.HasValue && appointment.Status.Value != 3 /* completed */select appointment
).OrderBy(a => a.StartDate).First().AppointmentType,
ProviderTypeID = (leadProvider != null ? leadProvider.ProviderTypeID : 0),
Provider = leadProvider
}).ToList();
вообще, база данных не только запросы к ней и таблички...ее также приходится поддерживать, сопровождать, она влияет на производительность системы в целом и даже больше, чем ее клиенты, это неотъемлемая составляющая серьезной системы, и linq to sql не предназначен для того, чтобы эту составляющую убрать полностью...нужно в первую очередь исходить из требований к самой базе.
Если коротко:
1) СП стоит рассматривать не как средство подтюнить производительность, а как средство инкапсуляции БД/внешние интерфейсы. Другими словами — способ дать доступ к данным, не открывая всех внутренностей.
2) +1 к "не использовать Linq2SQL в серьёзных системах".
3) Linq2SQL уже не модно — EF очередное наше всё.
Здравствуйте, DuШes, Вы писали:
DШ>позволяющие убрать непосредственное общение со скриптами, но общий минус у всех один и тот же — это возможность получения такого плана выполнения, DШ>который и в страшном сне не приснится ну и соотвественно медленные запросы...те вещи, которые являются родными для sql определенного диалекта ну никак не перенести в конструкции c# linq (функции обработки данных, преобразования типов), к тому же, если речь идет о сложной логике обработки данных (скажем, некие предпросчеты, или запросы к распределенным системам, построенным на linked servers) то гораздо выгоднее и компактнее написать такую логику в процедурах и использовать их как методы linq to sql context-а... (уж не говорю о том, что сложно построить linq контекcт, построенный на нескольких базах данных)
Как я понял из сообщения топикстартера, его начальство надеялось получить прирост производительности путем тупого переноса sql-я, генерируемого LINQ2SQL-ем, в хранимые процедуры. О ручном тюнинге sql-я речи и не было.
[...]
L>Как я понял из сообщения топикстартера, его начальство надеялось получить прирост производительности путем тупого переноса sql-я, генерируемого LINQ2SQL-ем, в хранимые процедуры. О ручном тюнинге sql-я речи и не было.
да я собственно и не спорю...соглашусь с вашим постом, что прироста производительности не будет, речь даже не о том, что sql сервер умеет кешировать не только скомпилированные планы процедур, но также и вызовы простых запросов.
вообще, желание нормальное — увеличить производительность — но трудозатраты очень большие, даже не только потому, что тупо перенести запросы в процедуры не получится, придется переделывать вообще механизм доступа к данным и думать о тех orm классах, которые были сгенерированы на основе таблиц...
в той постановке задачи, которая присуствует сейчас, самая большая проблема следующая:
желание оставить классы сгенерированной схемы и работать с ними будет затруднительно, потому что не каждая хранимка (метод схемы) будет возвращать тот набор полей, которые потребуется для маппинга в сгенерированные классы, иначе, придется ручками описывать те классы, которые ранее нам генерировал компилятор для анонимных типов
вообще на мой взгляд или работать с linq по старому без процедур или не работать вообще, иначе сразу можно застрелиться
Здравствуйте, DuШes, Вы писали:
DШ>да я собственно и не спорю...соглашусь с вашим постом, что прироста производительности не будет, речь даже не о том, что sql сервер умеет кешировать не только скомпилированные планы процедур, но также и вызовы простых запросов.
Откуда взялись "скомпилированные планы процедур"? Такого понятия вроде нет. Понятие План применимо только к запросам.
Здравствуйте, Lloyd, Вы писали:
L>Здравствуйте, DuШes, Вы писали:
DШ>>да я собственно и не спорю...соглашусь с вашим постом, что прироста производительности не будет, речь даже не о том, что sql сервер умеет кешировать не только скомпилированные планы процедур, но также и вызовы простых запросов.
L>Откуда взялись "скомпилированные планы процедур"? Такого понятия вроде нет. Понятие План применимо только к запросам.
S>Оптимизировать никто не будет. Предлагается текущие запросы, сформированные LINQ просто скопировать на сервер и сделать из них хранимые процедуры. Про кэш я сказал. На это мне ответили, что запросов тысячи и что кэш здесь не поможет. Я не силен в этом, но как-то сомневаюсь. Зачем же он тогда нужен, если не поможет. Можете привести аргументы, статьи какие-нибудь. Буду очень признателен
Тогда это бред. Сейчас серверы кэшируют любые запросы и планы запросов.
S>Если коротко: S>1) СП стоит рассматривать не как средство подтюнить производительность, а как средство инкапсуляции БД/внешние интерфейсы. Другими словами — способ дать доступ к данным, не открывая всех внутренностей. S>2) +1 к "не использовать Linq2SQL в серьёзных системах". S>3) Linq2SQL уже не модно — EF очередное наше всё.
В общем мы пришли к выводу, что автор подставляет шефа
Шеф знает, что лучше хранимки, но не знает зачем. Или не хочет объяснять.
Я уже, к сожалению, столкнулся с вариантом, когда объяснение серьёзными терминами или абстракциями, знание которых отсутствует у исполнителей, наносит только вред.
Здравствуйте, DuШes, Вы писали:
DШ>Здравствуйте, Lloyd, Вы писали:
DШ>[...]
L>>Как я понял из сообщения топикстартера, его начальство надеялось получить прирост производительности путем тупого переноса sql-я, генерируемого LINQ2SQL-ем, в хранимые процедуры. О ручном тюнинге sql-я речи и не было.
DШ>да я собственно и не спорю...соглашусь с вашим постом, что прироста производительности не будет, речь даже не о том, что sql сервер умеет кешировать не только скомпилированные планы процедур, но также и вызовы простых запросов.
DШ>вообще, желание нормальное — увеличить производительность — но трудозатраты очень большие, даже не только потому, что тупо перенести запросы в процедуры не получится, придется переделывать вообще механизм доступа к данным и думать о тех orm классах, которые были сгенерированы на основе таблиц...
DШ>в той постановке задачи, которая присуствует сейчас, самая большая проблема следующая: DШ>желание оставить классы сгенерированной схемы и работать с ними будет затруднительно, потому что не каждая хранимка (метод схемы) будет возвращать тот набор полей, которые потребуется для маппинга в сгенерированные классы, иначе, придется ручками описывать те классы, которые ранее нам генерировал компилятор для анонимных типов
DШ>вообще на мой взгляд или работать с linq по старому без процедур или не работать вообще, иначе сразу можно застрелиться
А почему для всех свет клином сошелся на процедурах? Есть много других средств инкапсуляции в SQL, есть View, которыя для запросов подходят гораздо лучше процедур, есть instead of триггеры, которые позволяют работать с вьюхами, как с таблицами.
Я вообще не вижу смыла делать CRUD на процедурах.
И никакого геморроя потом в программе не появляет, можно использовать все тот же Linq\EF.
Здравствуйте, gandjustas, Вы писали:
G>А почему для всех свет клином сошелся на процедурах? Есть много других средств инкапсуляции в SQL, есть View, которыя для запросов подходят гораздо лучше процедур,
View сложнее оптимизировать. Запросы к View приводят к не всегда предсказуемым результатам в плане производительности и оптимизатору с ними тяжелее.
G>есть instead of триггеры, которые позволяют работать с вьюхами, как с таблицами.
Триггеры не очевидны. И опять же проблемы с оптимизацией — изменяешь одно маленькое поле в одной маленькой табличке, а она порождает каскадное обновление всей базы и это не возможно предсказать, если не знаешь всю структуру базы с потрохами и логикой. Процедуры в этом плане очевиднее и предсказуемее.
G>Я вообще не вижу смыла делать CRUD на процедурах.
CRUD — нет, а вот в логике по сложнее я скорее за процедуры, чем за View и триггеры.
Просто в БД abstraction penalty дороже обходится и гораздо меньше возможности дать понять разработчику что стоит за простым обращением.
Здравствуйте, IB, Вы писали:
IB>Здравствуйте, gandjustas, Вы писали:
G>>А почему для всех свет клином сошелся на процедурах? Есть много других средств инкапсуляции в SQL, есть View, которыя для запросов подходят гораздо лучше процедур, IB>View сложнее оптимизировать. Запросы к View приводят к не всегда предсказуемым результатам в плане производительности и оптимизатору с ними тяжелее.
Это я знаю. В этом конкретном случае видимно никто и не собирался залить в процедуры для оптимизации, обычно их применяют только для инкапсуляции, view в этом плане гороздо выгоднее.
G>>есть instead of триггеры, которые позволяют работать с вьюхами, как с таблицами. IB>Триггеры не очевидны. И опять же проблемы с оптимизацией — изменяешь одно маленькое поле в одной маленькой табличке, а она порождает каскадное обновление всей базы и это не возможно предсказать, если не знаешь всю структуру базы с потрохами и логикой. Процедуры в этом плане очевиднее и предсказуемее.
ИМХО нет разницы править 4 процедуры или вьюху и 3 триггера.
G>>Я вообще не вижу смыла делать CRUD на процедурах. IB>CRUD — нет, а вот в логике по сложнее я скорее за процедуры, чем за View и триггеры.
Linq\EF сейчас обеспечивает только CRUD. Любую логику, которая должна выполняться в СУБД придется делать в процедурах\функциях.
Спасибо всем ответившим!
Даже не знаю что делать
Просто тут ситуация ещё запутаннее, чем может показаться на первый взгляд.
Есть система, которая написана на хранимках и текстовых запросах к БД. Сейчас переписываем все на LINQ и появились тормоза в системе. Шеф, старой закалки, решил, что это все из-за LINQ (хотя реально в системе (production) он не используется) и сказал, что LINQ-зло, но отказываться нельзя, а так как можно стучаться к хранимкам из LINQ, давайте делать так.
Как я понял, у него просто каша в голове. Посоветовали ему взять спеца по БД и с ним проконсультироваться, где у нас Bottle-neck в БД.
Ещё раз спасибо за советы. Подумаем, что можно тут сделать.
Здравствуйте, Spender, Вы писали:
S>Проблема в следующем. Имеется база данных доступ к которой организован через запросы LINQ to SQL. Шеф сказал, что от LINQ он отказываться не хочет, но теперь вместо доступа к таблицам и полям БД надо будет использовать LINQ к Store Procedure. Аргументом к этому служит то, что SQL-серверу не надо будет компилировать запрос каждый раз и это увеличит производительность.
Если все это правда, то твой шеф — кретин. По совокупности следующих пунктов:
1. LINQ to SQL, завязаный только на хранимые процедуры — это "LINQ to SQL" без слова "LINQ". Что там собственно останется-то хорошего, если оттуда убрать запросы?
2. Запросы компилируются и скорости перенос тех же самых запросов в хранимки не добавит. Это известный факт.
3. Работать с хранимками намного менее удобно, чем с кодом, по многим причинам. Т.е. хранимки будут тормозить разработку.
4. И самое главное: совершенное самодурство и кретинизм делать что-то потому что "я думаю что так будет быстрее". Промерить не судьба? Может у вас там где-нибудь StringBuilder поставить нужно вместо string += и все летать начнет? И переписывать ничего не нужно будет? Может быть есть только один тормозной запрос и его стоит вынуть и оптимизировать, вместо того, чтобы делать это для всех подряд? Если делается расчет на будущее — может стоит сначала написать нагрузочные тесты?
Здравствуйте, Spender, Вы писали:
S>Спасибо всем ответившим! S>Даже не знаю что делать S>Просто тут ситуация ещё запутаннее, чем может показаться на первый взгляд. S>Есть система, которая написана на хранимках и текстовых запросах к БД. Сейчас переписываем все на LINQ и появились тормоза в системе. Шеф, старой закалки, решил, что это все из-за LINQ (хотя реально в системе (production) он не используется) и сказал, что LINQ-зло, но отказываться нельзя, а так как можно стучаться к хранимкам из LINQ, давайте делать так. S>Как я понял, у него просто каша в голове. Посоветовали ему взять спеца по БД и с ним проконсультироваться, где у нас Bottle-neck в БД.
Конечно любую оптимизацию надо начинать с поиска узкого места, но шеф ваш имхо вполне прав. Использую линк к сторам вы получите compile time проверки, что выгодно отличает этот подход от простого вызова при помощи ADO.NET
Здравствуйте, Jakobz, Вы писали:
J>Здравствуйте, Spender, Вы писали:
S>>Проблема в следующем. Имеется база данных доступ к которой организован через запросы LINQ to SQL. Шеф сказал, что от LINQ он отказываться не хочет, но теперь вместо доступа к таблицам и полям БД надо будет использовать LINQ к Store Procedure. Аргументом к этому служит то, что SQL-серверу не надо будет компилировать запрос каждый раз и это увеличит производительность.
J>Если все это правда, то твой шеф — кретин. По совокупности следующих пунктов:
Я бы на вашем месте не был так котегоричен.
J>1. LINQ to SQL, завязаный только на хранимые процедуры — это "LINQ to SQL" без слова "LINQ". Что там собственно останется-то хорошего, если оттуда убрать запросы?
останется compile time проверки вызова стор.
J>2. Запросы компилируются и скорости перенос тех же самых запросов в хранимки не добавит. Это известный факт.
Разница огромна, при использовании линка запросы SQL генерит линк, при использовании явных запросов или стор — вы сами.
J>3. Работать с хранимками намного менее удобно, чем с кодом, по многим причинам. Т.е. хранимки будут тормозить разработку.
Работать с хранимкапми на порядок удобнее, намного проще например отлаживать план выполнения.
J>4. И самое главное: совершенное самодурство и кретинизм делать что-то потому что "я думаю что так будет быстрее". Промерить не судьба? Может у вас там где-нибудь StringBuilder поставить нужно вместо string += и все летать начнет? И переписывать ничего не нужно будет? Может быть есть только один тормозной запрос и его стоит вынуть и оптимизировать, вместо того, чтобы делать это для всех подряд? Если делается расчет на будущее — может стоит сначала написать нагрузочные тесты?
найти узкое место — это действительно надо в первую очередь.
Здравствуйте, gandjustas, Вы писали:
G> В этом конкретном случае видимно никто и не собирался залить в процедуры для оптимизации, обычно их применяют только для инкапсуляции, view в этом плане гороздо выгоднее.
Проблема в том, что можно доинкапсулироваться до полной потери производительности.
G>ИМХО нет разницы править 4 процедуры или вьюху и 3 триггера.
Править нет. А вот когда нужно понять что происходит или что-то поменять с предсказуемым результатом — процедуры рулят.
Здравствуйте, Tom, Вы писали:
S>>Как я понял, у него просто каша в голове. Посоветовали ему взять спеца по БД и с ним проконсультироваться, где у нас Bottle-neck в БД. Tom>Конечно любую оптимизацию надо начинать с поиска узкого места, но шеф ваш имхо вполне прав. Использую линк к сторам вы получите compile time проверки, что выгодно отличает этот подход от простого вызова при помощи ADO.NET
Совсем не обязательно. Мы на одном проекте использовали типизированые обертки над хранимками (свой кастом тул), внутри которого вполне себе удачно использовался ADO.NET
Здравствуйте, Jakobz, Вы писали:
J>1. LINQ to SQL, завязаный только на хранимые процедуры — это "LINQ to SQL" без слова "LINQ". Что там собственно останется-то хорошего, если оттуда убрать запросы?
+ маппиниг резалтсета хранимой процедуры на объекты.
+ tracking изменений
Здравствуйте, Jakobz, Вы писали:
J>4. И самое главное: совершенное самодурство и кретинизм делать что-то потому что "я думаю что так будет быстрее". Промерить не судьба? Может у вас там где-нибудь StringBuilder поставить нужно вместо string += и все летать начнет? И переписывать ничего не нужно будет? Может быть есть только один тормозной запрос и его стоит вынуть и оптимизировать, вместо того, чтобы делать это для всех подряд? Если делается расчет на будущее — может стоит сначала написать нагрузочные тесты?
Может я телефончик его дам, Вы ему тоже это скажете. Наша команда замудохалась объяснять ему это. Нагрузочные тесты у нас выглядят так. Берутся все программисты и начинают тыкать по кнопочкам, в это время смотрится загрузка SQL сервера.
Я тут ещё одно уточнение хочу вставить.
Проблема именно в том, что SQL сервер перестает отвечать клиентам. Т.е. считается, что он очень сильно нагружается из-за того, что ему каждый раз приходится компилить запросы. Не знаю, очивидно ли это было из предыдуших моих постов или нет. Но так, на всякий случай.
Здравствуйте, Tom, Вы писали:
J>>Если все это правда, то твой шеф — кретин. По совокупности следующих пунктов: Tom>Я бы на вашем месте не был так котегоричен.
А почему бы не был? Почему бы шефу не являться кретином, и почему бы мне это здесь не констатировать?
J>>1. LINQ to SQL, завязаный только на хранимые процедуры — это "LINQ to SQL" без слова "LINQ". Что там собственно останется-то хорошего, если оттуда убрать запросы? Tom>останется compile time проверки вызова стор.
Скорее строго-типизированная обертка, чем полноценная проверка. Проверять что параметры хранимке переданы правильно, оно не будет. И даже что она на самом деле есть в базе — не проверит.
От LINQ еще многое останется, на самом деле. Я просто хотел напомнить что LINQ в этой технологии все-таки ключевой элемент.
J>>2. Запросы компилируются и скорости перенос тех же самых запросов в хранимки не добавит. Это известный факт. Tom>Разница огромна, при использовании линка запросы SQL генерит линк, при использовании явных запросов или стор — вы сами.
Я имел ввиду что перенос сгенеренных линкой запросов в хранимки не даст прироста. Но можно и переписать все, конечно, с полной уверенностью что "уж я-то шарю в базах, уж я-то всяко сделаю быстрее, чем тупой генератор". Но это обратно по поводу самодуров и кретинов. Далеко не факт что это даст прирост чистыми (см. "преждевременная оптимизация" и "5% кода занимают 95% времени").
Tom>Работать с хранимкапми на порядок удобнее, намного проще например отлаживать план выполнения.
Работать с ассемблером тоже было бы удобнее, если бы все занимались исключительно оптимизацией.
Минусов у хранимок навалом. Мне они очевидны и здесь сто раз уже обсуждались. Расписать основные?
Tom>найти узкое место — это действительно надо в первую очередь.
Нужно было это поставить первым и единственным пунктом. Остальные аргументы — до кучи, и, если копнуть поглубже, действительно могут быть спорны.
Здравствуйте, Lloyd, Вы писали:
L>Здравствуйте, Jakobz, Вы писали:
J>>1. LINQ to SQL, завязаный только на хранимые процедуры — это "LINQ to SQL" без слова "LINQ". Что там собственно останется-то хорошего, если оттуда убрать запросы?
L>+ маппиниг резалтсета хранимой процедуры на объекты.
вот это и есть ужос, который превратится в будущем в еще более ужос, когда придется расширять классы или структуру таблиц...
к тому же, самое плохое в linq to sql это то, что нет обратного маппинга из классов схемы в базу данных...в том же самом DX XPO эта проблема решена (не сочтите за рекламу )
L>+ tracking изменений
tracking изменений — где его вы видели, дерганье методов/событий из акксосоров свойств? ну если это имеете ввиду, то это совсем не трекинг
Здравствуйте, DuШes, Вы писали:
J>>>1. LINQ to SQL, завязаный только на хранимые процедуры — это "LINQ to SQL" без слова "LINQ". Что там собственно останется-то хорошего, если оттуда убрать запросы?
L>>+ маппиниг резалтсета хранимой процедуры на объекты.
DШ>вот это и есть ужос, который превратится в будущем в еще более ужос, когда придется расширять классы или структуру таблиц...
как тебе поможет его отсутствие "когда придется расширять классы или структуру таблиц"
L>>+ tracking изменений DШ>tracking изменений — где его вы видели, дерганье методов/событий из акксосоров свойств?
Нет, я имел в виду, что datacontext отслеживает изменения, произведенные над сущностью, и по SubmitChanes сливает их в базу.
Реализуется это действительно через привязку к соответствующим событиям, но это не единственный вариант.
DШ>ну если это имеете ввиду, то это совсем не трекинг
L>>>+ маппиниг резалтсета хранимой процедуры на объекты.
DШ>>вот это и есть ужос, который превратится в будущем в еще более ужос, когда придется расширять классы или структуру таблиц...
L>как тебе поможет его отсутствие "когда придется расширять классы или структуру таблиц"
не поможет, но и не помешает — а если не будет смысла его использования, зачем он будет вообще нужен...
т.е. речь о чем? есть результат хранимой процедуры, возвращаю два поля, name & id, мне нужно будет создать класс-враппер для этих получаемых данных, пометить их определенными атрибутами и в принципе начать использовать...расширяю выборку, нужно возвращать уже три поля, скажем добавилось lastname, меняю в процедуре, меняю враппер...
это если бы стали использовать методы/процедуры в linq
классическая схема — тот же самый класс по сути враппер над данными, datareader, ну и ручное кодирование — строка this.lastname = datareader.read(...)
трудозатраты по сути такие же, более того, можно за час работы написать свой orm враппер класс, который по имени свойства из класса сопоставит соотвествующее поле из выборки ...не в этом дело, просто пытаюсь доказать, что в данном случае, когда будут применяться процедуры в линке, необходимость в нем вообще отпадает
L>А что такое по-вашему трекинг?
ну уж по крайне мере не так, уж лучше через аспекты
Здравствуйте, Spender, Вы писали:
S>Здравствуйте, Jakobz, Вы писали:
J>>4. И самое главное: совершенное самодурство и кретинизм делать что-то потому что "я думаю что так будет быстрее". Промерить не судьба? Может у вас там где-нибудь StringBuilder поставить нужно вместо string += и все летать начнет? И переписывать ничего не нужно будет? Может быть есть только один тормозной запрос и его стоит вынуть и оптимизировать, вместо того, чтобы делать это для всех подряд? Если делается расчет на будущее — может стоит сначала написать нагрузочные тесты?
S>Может я телефончик его дам, Вы ему тоже это скажете. Наша команда замудохалась объяснять ему это. Нагрузочные тесты у нас выглядят так. Берутся все программисты и начинают тыкать по кнопочкам, в это время смотрится загрузка SQL сервера.
Здравствуйте, DuШes, Вы писали:
DШ>классическая схема — тот же самый класс по сути враппер над данными, datareader, ну и ручное кодирование — строка this.lastname = datareader.read(...) DШ>трудозатраты по сути такие же,
Какие тогда притензии к стандартному мапперу? Озвучь, пожалуйста.
DШ>более того, можно за час работы написать свой orm враппер класс, который по имени свойства из класса сопоставит соотвествующее поле из выборки ...не в этом дело, просто пытаюсь доказать, что в данном случае, когда будут применяться процедуры в линке, необходимость в нем вообще отпадает
Зачем что-то писать, если это уже есть в составе Linq2Sql
L>>А что такое по-вашему трекинг?
DШ>ну уж по крайне мере не так, уж лучше через аспекты
Здравствуйте, Lloyd, Вы писали:
L>Здравствуйте, DuШes, Вы писали:
DШ>>классическая схема — тот же самый класс по сути враппер над данными, datareader, ну и ручное кодирование — строка this.lastname = datareader.read(...) DШ>>трудозатраты по сути такие же,
L>Какие тогда притензии к стандартному мапперу? Озвучь, пожалуйста.
прежде чем озвучивать свои претензии я не услышал вашего мнения о преимуществах использования "стандартного" маппера
DШ>>более того, можно за час работы написать свой orm враппер класс, который по имени свойства из класса сопоставит соотвествующее поле из выборки ...не в этом дело, просто пытаюсь доказать, что в данном случае, когда будут применяться процедуры в линке, необходимость в нем вообще отпадает
L>Зачем что-то писать, если это уже есть в составе Linq2Sql
вместе с напильником...
L>>>А что такое по-вашему трекинг?
DШ>>ну уж по крайне мере не так, уж лучше через аспекты
L>Чем лучше?
ну по крайне мере хотя бы тем, что не нужно ВООБЩЕ задумываться о включении какой-либо логики в свойства, я уж не спрашиваю вас о том, как вы сделайте трекинг полей/вызовов методов без аспектов
Здравствуйте, DuШes, Вы писали:
DШ>>>классическая схема — тот же самый класс по сути враппер над данными, datareader, ну и ручное кодирование — строка this.lastname = datareader.read(...) DШ>>>трудозатраты по сути такие же,
L>>Какие тогда притензии к стандартному мапперу? Озвучь, пожалуйста.
DШ>прежде чем озвучивать свои претензии я не услышал вашего мнения о преимуществах использования "стандартного" маппера
Он есть
качественно оттестирован толпой тестеров в микрософте
по нему есть документация
если с ним возникнет какая-то проблема, существует большое кол-во людей, которые его использовали в очень разных сценариях и они смогут мне помочь
DШ>>>более того, можно за час работы написать свой orm враппер класс, который по имени свойства из класса сопоставит соотвествующее поле из выборки ...не в этом дело, просто пытаюсь доказать, что в данном случае, когда будут применяться процедуры в линке, необходимость в нем вообще отпадает
L>>Зачем что-то писать, если это уже есть в составе Linq2Sql
DШ>вместе с напильником...
Что "вместе с напильником"?
L>>>>А что такое по-вашему трекинг?
DШ>>>ну уж по крайне мере не так, уж лучше через аспекты
L>>Чем лучше?
DШ>ну по крайне мере хотя бы тем, что не нужно ВООБЩЕ задумываться о включении какой-либо логики в свойства,
Задумываться об этом действительно не стоит, т.к. эту проблему вполне себе решает Linq2Sql-овский дизайнер.
DШ>я уж не спрашиваю вас о том, как вы сделайте трекинг полей/вызовов методов без аспектов
Это worst practise — работать с полями напрямую при наличии соответствующих свойств.
Я в свою очередь спрошу как вы собрались делать трекинг полей через аспекты, если я захочу работать с ними через reflection
Здравствуйте, kenzo_u, Вы писали:
_>А может лучше все запросы держать в одном месте? Либо только в виде ХП, либо только в коде программы в DAL-слое?
Если есть DAL, то где конкретно находятся запросы для квалифицированного разработчика — фиолетово. Для стажеров — жестко, только хранимки.
L> L>Он есть L>качественно оттестирован толпой тестеров в микрософте
настолько качественно, что забыли обратный маппинг в базу
L>по нему есть документация L>если с ним возникнет какая-то проблема, существует большое кол-во людей, которые его использовали в очень разных сценариях и они смогут мне помочь
да, эти люди начинают такие темы, в которой мы сейчас и присутствуем L>
вообщем, linq to sql (именно to sql) насктолько хорош, насколько его благополучно похоронили
DШ>>вместе с напильником...
L>Что "вместе с напильником"?
те проблемы, о которых писал, если говорим о процедурах
L>Задумываться об этом действительно не стоит, т.к. эту проблему вполне себе решает Linq2Sql-овский дизайнер.
да, наверно у вас не было такой практики, когда полностью приходится убивать всю схему и генерировать снова , только для того, чтобы учесть все изменения, внесенные в базу после того, как схема уже была сгенерирована ... особенно приятно, когда есть вычисляемые поля/свойства, реализованный в partial classes
L>Я в свою очередь спрошу как вы собрались делать трекинг полей через аспекты, если я захочу работать с ними через reflection
ну мы так далеко зайдем вплоть до msil injection
Здравствуйте, DuШes, Вы писали:
DШ>вообщем, linq to sql (именно to sql) насктолько хорош, насколько его благополучно похоронили
Его похоронили не из-за того, что наколенные решения лучше, а из-за того, что есть EF, который во многом дублирует функциональность LINQ2SQL-а.
Кстати, ты вроде как пообещал озвучить претенции после того, как я приведу преимущества стандартного маппера. Ваш ход.
DШ>>>вместе с напильником...
L>>Что "вместе с напильником"? DШ>те проблемы, о которых писал, если говорим о процедурах
Напиши, пожалуйста полное предложение. Не получается у меня из "вместе с напильником" и "те проблемы, о которых писал, если говорим о процедурах" составить что-то осмысленное.
L>>Задумываться об этом действительно не стоит, т.к. эту проблему вполне себе решает Linq2Sql-овский дизайнер.
DШ>да, наверно у вас не было такой практики, когда полностью приходится убивать всю схему и генерировать снова , только для того, чтобы учесть все изменения, внесенные в базу после того, как схема уже была сгенерирована ... особенно приятно, когда есть вычисляемые поля/свойства, реализованный в partial classes
Конечно, у меня не возникало таких проблем. У нас на проекте есть сложившаяся процедура внесения изменений в схему базы, благодаря которой нет необходимости "убивать всю схему и генерировать снова". Это экономит кучу времени. Рекомендую вам с коллегами сесть как-нить вечерком с пивком и решить раз и навсегда, как по-правильному вносить изменения.
L>>Я в свою очередь спрошу как вы собрались делать трекинг полей через аспекты, если я захочу работать с ними через reflection DШ>ну мы так далеко зайдем вплоть до msil injection
Здравствуйте, Lloyd, Вы писали: L>Кстати, ты вроде как пообещал озвучить претенции после того, как я приведу преимущества стандартного маппера. Ваш ход. L>>>Что "вместе с напильником"? DШ>>те проблемы, о которых писал, если говорим о процедурах L>Напиши, пожалуйста полное предложение. Не получается у меня из "вместе с напильником" и "те проблемы, о которых писал, если говорим о процедурах" составить что-то осмысленное.
как-раз и пытался доказать, что преимуществ кроме как визуального представления схемы и картинок нет...и в ваших доводах не увидел.
и раз уж речь зашла именно иб использовании процедур в рамках linq, то давайте говорить о процедурах — вот тут проблема а не в стандартном маппере на таблицы (мух отделите пожалуйста)..когда говорим о процедурах (а лично для себя не вижу пока ситуации, чтобы не использовать процедуры) вот тут и возникают проблемы с маппингом в неизвестность и проблемы синхронизации возвращаемых данных с классама-врапперами на стороне шарпа...странно, что вы их в упор не видите...хотя бы то, что стандартный враппер более-менее сложную процедуру прсото не поймет и не сгенерирует на основании данных, возвращаемых процедурой, вменяемый класс, который можно было бы потом применять в рамках c#.
насчет претензий — слова "претензия" означает несколько иное, я линк не ругал к вашему сведению, есть у него область приминения, а именно, настольные приложения или небольшие низконагруженные сайты..
ладно, пусть это будет претензия
1. не умеет работать с распределенными базами, где имеет место быть несколько баз и несколько серверов — или же вы используете несколько контекстов? тогда может быть и несколько соединений?
2. нельзя создать класс-сущность, маппируемую в разные таблицы...
3. нельзя без напильника научить методы возвращать наборы объектовбез написания вручную классов-врапперов няд этими данными
L>Конечно, у меня не возникало таких проблем. У нас на проекте есть сложившаяся процедура внесения изменений в схему базы, благодаря которой нет необходимости "убивать всю схему и генерировать снова". Это экономит кучу времени. Рекомендую вам с коллегами сесть как-нить вечерком с пивком и решить раз и навсегда, как по-правильному вносить изменения.
вот и поделитесь — пока на ум только одно приходит, где-то кричится о том, что добавили новое поле в таблицу, и вручную делаем сотвествующее свойство в классе с указанием, откуда оно смаппировано — это если не убивая часть схемы
поверьте, все изменения у нас скриптуются и база версионная, для этого пиво не нужно, а под пивом можно много чего натворить
L>>>Я в свою очередь спрошу как вы собрались делать трекинг полей через аспекты, если я захочу работать с ними через reflection DШ>>ну мы так далеко зайдем вплоть до msil injection
L>не поможет, уверяю тебя.
это вот про что сейчас? ...можно конечно скатиться в сторону обсуждения плюсов и минусов использования аспектов, тогда да, наверно — не поможет вам
Здравствуйте, Spender, Вы писали:
S>Я тут ещё одно уточнение хочу вставить. S>Проблема именно в том, что SQL сервер перестает отвечать клиентам. Т.е. считается, что он очень сильно нагружается из-за того, что ему каждый раз приходится компилить запросы. Не знаю, очивидно ли это было из предыдуших моих постов или нет. Но так, на всякий случай.
Такое уж точно не из-за компиляции запросов.
Загрузку как мониторите? Когда и кому перестает отвечать? Может быть дело в блокировках? Может быть опять же в каком-то одном запросе и проблему решит один индекс? Какой запрос тормозит и жрет ресурсы?
Открывайте activity monitor, sql server profiler. Добавляйте логгирование. Попытайтесь изолировать проблему: посмотрите при каких действиях подвисает, а при каких — нет, от чего это зависит. Напишите нагрузочные тесты, воспроизводящие проблему. Понизьте уровень изоляции транзакций и посмотрите помогает или нет. Посмотрите планы самых ресурсоёмких запросов.
Короче нужно всего-то найти один bottleneck и устранить. Мой совет: найдите его сами, исправьте, и покажите начальнику. Если он кретин только в техническом плане, может он будет после этого считаться с вашим мнением, вместо того, чтобы принимать кретинские технические решения.
Здравствуйте, DuШes, Вы писали:
L>>Напиши, пожалуйста полное предложение. Не получается у меня из "вместе с напильником" и "те проблемы, о которых писал, если говорим о процедурах" составить что-то осмысленное.
DШ>как-раз и пытался доказать, что преимуществ кроме как визуального представления схемы и картинок нет...и в ваших доводах не увидел.
в моих доводах ни слова не было про это.
DШ>и раз уж речь зашла именно иб использовании процедур в рамках linq, то давайте говорить о процедурах — вот тут проблема а не в стандартном маппере на таблицы (мух отделите пожалуйста)..
Маппер на таблицы и маппер на резалтсет процедуры — это один и тот же маппер.
DШ>когда говорим о процедурах (а лично для себя не вижу пока ситуации, чтобы не использовать процедуры) вот тут и возникают проблемы с маппингом в неизвестность и проблемы синхронизации возвращаемых данных с классама-врапперами на стороне шарпа...странно, что вы их в упор не видите...хотя бы то, что стандартный враппер более-менее сложную процедуру прсото не поймет и не сгенерирует на основании данных, возвращаемых процедурой, вменяемый класс, который можно было бы потом применять в рамках c#.
Маппер на занимается генерацией этого класса. Его задача — результат выполнения процедуры залить в тот класс, в который ему скажут.
DШ>насчет претензий — слова "претензия" означает несколько иное, я линк не ругал к вашему сведению, есть у него область приминения, а именно, настольные приложения или небольшие низконагруженные сайты.. DШ>ладно, пусть это будет претензия DШ>1. не умеет работать с распределенными базами, где имеет место быть несколько баз и несколько серверов — или же вы используете несколько контекстов? тогда может быть и несколько соединений?
При чем тут маппер?
DШ>2. нельзя создать класс-сущность, маппируемую в разные таблицы...
Я так понимаю ты работаешь с процедурами. Так вот в этом случае ты вполне можешь указать, одну и ту же сущность как результат работы разных процедур. Единственно, ты не сможешь воспользоваться ею для update-а в базу.
DШ>3. нельзя без напильника научить методы возвращать наборы объектов без написания вручную классов-врапперов няд этими данными
Чего-чего? Еще раз и помедленнее.
Какие методы? Почему нельзя? При чем тут маппер?
L>>Конечно, у меня не возникало таких проблем. У нас на проекте есть сложившаяся процедура внесения изменений в схему базы, благодаря которой нет необходимости "убивать всю схему и генерировать снова". Это экономит кучу времени. Рекомендую вам с коллегами сесть как-нить вечерком с пивком и решить раз и навсегда, как по-правильному вносить изменения.
DШ>вот и поделитесь — пока на ум только одно приходит, где-то кричится о том, что добавили новое поле в таблицу, и вручную делаем сотвествующее свойство в классе с указанием, откуда оно смаппировано — это если не убивая часть схемы
Никто никуда не кричит. Тот, кто изменяет схему, обязан изменить и соответствующие entity. Самый простой способ — это внести это изменение вручную в dbml.
L>>>>Я в свою очередь спрошу как вы собрались делать трекинг полей через аспекты, если я захочу работать с ними через reflection DШ>>>ну мы так далеко зайдем вплоть до msil injection
L>>не поможет, уверяю тебя.
DШ>это вот про что сейчас? ...можно конечно скатиться в сторону обсуждения плюсов и минусов использования аспектов, тогда да, наверно — не поможет вам
А вы не личности не переходите. У нас проблем с Linq2Sql-м как-то не наблюдается.
Кстати, ты так и не сказал, чем AOP будет лучше по сравнению с банальным генерированием сущностей из dbml-я.
Здравствуйте, Jakobz, Вы писали:
J>Такое уж точно не из-за компиляции запросов. J>Загрузку как мониторите? Когда и кому перестает отвечать? Может быть дело в блокировках? Может быть опять же в каком-то одном запросе и проблему решит один индекс? Какой запрос тормозит и жрет ресурсы? J>Открывайте activity monitor, sql server profiler. Добавляйте логгирование. Попытайтесь изолировать проблему: посмотрите при каких действиях подвисает, а при каких — нет, от чего это зависит. Напишите нагрузочные тесты, воспроизводящие проблему. Понизьте уровень изоляции транзакций и посмотрите помогает или нет. Посмотрите планы самых ресурсоёмких запросов. J>Короче нужно всего-то найти один bottleneck и устранить. Мой совет: найдите его сами, исправьте, и покажите начальнику. Если он кретин только в техническом плане, может он будет после этого считаться с вашим мнением, вместо того, чтобы принимать кретинские технические решения.
Если бы я все это умел У нас есть человек специальный для этого. Он полностью занимается БД на стороне SQL сервера. Может даже оптимизирует что-то там. Но вряд ли.
Спасибо за совет. Попробую все это рассказать шефу.
Здравствуйте, Lloyd, Вы писали: L>>>не поможет, уверяю тебя.
[skipped]
я думаю, весь разговор скатился к придираниям к словам; под linq to sql и понимайте маппер в/из базы данных, щас еще начнем обсуждать linq провайдеры ...
я вопринимаю linq to sql как некий FW, который диктует правила и накладывает ограничения для работы с данными, если возникает необходимость использования напильника как например для работы с процедурами и танцев с бубнами, то в топку..
L>А вы не личности не переходите. У нас проблем с Linq2Sql-м как-то не наблюдается. L>Кстати, ты так и не сказал, чем AOP будет лучше по сравнению с банальным генерированием сущностей из dbml-я.
по-моему, продолжать бесполезно я на личности не переходил, может вы
в рамках этой темы мы не будем обсуждать преимущества и минусы аспектов, если это вас так интересует, создайте новую тему или добро пожаловать в поиск...и мысль об аоп была рождена с учетом мысли ручного кодирования классов-врапперов
еще раз: если вы используете linq to sql, то слава богу и продолжайте его использовать, из все нашей дискуссии я остался убежден в том, что когда речь заходит об использовании процедур в линке, то тут его смысл теряется...из ваших слов все преимущества сводятся только:
1. Он есть
2. качественно оттестирован толпой тестеров в микрософте
3. по нему есть документация
4. если с ним возникнет какая-то проблема, существует большое кол-во людей, которые его использовали в очень разных сценариях и они смогут мне помочь
минусы я показал, жалко что не видите или не хотите видеть, зато:
Я так понимаю ты работаешь с процедурами. Так вот в этом случае ты вполне можешь указать, одну и ту же сущность как результат работы разных процедур. Единственно, ты не сможешь воспользоваться ею для update-а в базу.
Никто никуда не кричит. Тот, кто изменяет схему, обязан изменить и соответствующие entity. Самый простой способ — это внести это изменение вручную в dbml.
да, преимущества налицо , а теперь представим, что полностью перешли на использование процедур, так себе и представляю, как вы вручную пишите классы обертки над возвращаемыми данными...потому что ну не может и не умеет и не сможет linq to sql designer сгенерировать на основе t-sql кода то представление класса, которое требуется...за исключением редких банальных select * from;
предлагаю закрыть, судя по всему каждый останется при своем мнении
Здравствуйте, IB, Вы писали:
IB>Здравствуйте, kenzo_u, Вы писали:
_>>А может лучше все запросы держать в одном месте? Либо только в виде ХП, либо только в коде программы в DAL-слое? IB>Если есть DAL, то где конкретно находятся запросы для квалифицированного разработчика — фиолетово. Для стажеров — жестко, только хранимки.
Почему фиолетово для квалифицированного разработчика и почему только хранимки для стажеров?
Здравствуйте, DuШes, Вы писали:
DШ>я думаю, весь разговор скатился к придираниям к словам; под linq to sql и понимайте маппер в/из базы данных,
не надо менять предмет обсуждения. вы высказались про linq2sql-овский маппер, что он "ужос":
L>+ маппиниг резалтсета хранимой процедуры на объекты.
вот это и есть ужос, который превратится в будущем в еще более ужос, когда придется расширять классы или структуру таблиц...
Что вы тут имели в виду конкретно маппер или все-таки весь linq2sql целиком?
DШ>щас еще начнем обсуждать linq провайдеры ...
зачем? разговор ведь идет не о linq-е, и даже не о linq2sql-е, а о его маппере. зачем в этом котексте обсуждать какие-то провайдеры?
DШ>я вопринимаю linq to sql как некий FW, который диктует правила и накладывает ограничения для работы с данными, если возникает необходимость использования напильника как например для работы с процедурами и танцев с бубнами, то в топку..
Почему вы отказываетесь продемонсnрировать, какие у вас возникли проблемы с маппером?
DШ>в рамках этой темы мы не будем обсуждать преимущества и минусы аспектов, если это вас так интересует, создайте новую тему или добро пожаловать в поиск...и мысль об аоп была рождена с учетом мысли ручного кодирования классов-врапперов
Нет, меня интересует не OAP как таковое, а преимущества использования AOP перед использванием классов сущностей, создаваемых .dbml-ем.
DШ>еще раз: если вы используете linq to sql, то слава богу и продолжайте его использовать, из все нашей дискуссии я остался убежден в том, что когда речь заходит об использовании процедур в линке, то тут его смысл теряется...из ваших слов все преимущества сводятся только: DШ>
DШ> 1. Он есть
DШ> 2. качественно оттестирован толпой тестеров в микрософте
DШ> 3. по нему есть документация
DШ> 4. если с ним возникнет какая-то проблема, существует большое кол-во людей, которые его использовали в очень разных сценариях и они смогут мне помочь
еще раз повторюсь. выше по ветке я предполагал, что речь идет исключительно о маппере. давайте его и обсуждать, а не весь linq2sql целиком.
DШ>минусы я показал, жалко что не видите или не хотите видеть, зато: DШ>
DШ>Я так понимаю ты работаешь с процедурами. Так вот в этом случае ты вполне можешь указать, одну и ту же сущность как результат работы разных процедур. Единственно, ты не сможешь воспользоваться ею для update-а в базу.
DШ>
DШ>Никто никуда не кричит. Тот, кто изменяет схему, обязан изменить и соответствующие entity. Самый простой способ — это внести это изменение вручную в dbml.
DШ>да, преимущества налицо , а теперь представим, что полностью перешли на использование процедур, так себе и представляю, как вы вручную пишите классы обертки над возвращаемыми данными...потому что ну не может и не умеет и не сможет linq to sql designer сгенерировать на основе t-sql кода то представление класса, которое требуется...за исключением редких банальных select * from;
Еще раз напоминаю, что предмет обсуждения маппер, а не linq2sql designer.
DШ>предлагаю закрыть, судя по всему каждый останется при своем мнении
Предлагаю продолжить. Просто давай сузим тему до маппера исключительно и не будем с нее сходить. Ок?
Здравствуйте, Lloyd, Вы писали:
L>Здравствуйте, DuШes, Вы писали:
DШ>>я думаю, весь разговор скатился к придираниям к словам; под linq to sql и понимайте маппер в/из базы данных,
ну давайте продолжим L>Почему вы отказываетесь продемонсnрировать, какие у вас возникли проблемы с маппером?
я не говорил о проблемах с маппером, я вам уже объяснил, что маппер и дизайнер рассматриваю вместе, возможно поставил вас в заблуждение,и вот собственно невозможность его использования применительно к процедурам для построения схемы является той проблемой, которую пытался обозначить
L>не надо менять предмет обсуждения. вы высказались про linq2sql-овский маппер, что он "ужос": L>
L>+ маппиниг резалтсета хранимой процедуры на объекты.
L>вот это и есть ужос, который превратится в будущем в еще более ужос, когда придется расширять классы или структуру таблиц...
L>Что вы тут имели в виду конкретно маппер или все-таки весь linq2sql целиком?
не знаю как вы, но лично я не отделяю маппер и linq to sql data context designer и рассматриваю их как неделимое целое ... дык вот, маппер для процедур — его нет да в принципе теоретически быть не может, когда речь будет идти о возвращаемом датасете из нескольких таблиц...
в целом, если вы просто говорите что мол да, маппер свои задачи чисто по маппингу в/из базы/классы выполняет — то да, тут не соглашаться не с чем...это самое простое что есть забиндить поле из таблицы в соотвествующее свойство из класса,
но использовать чисто маппер из всего linq to sql ради только маппера вообще теряет смысл — и на этом давайте закончим наше обсуждение именно маппера, а не в целом linq to sql
теперь в целом по linq to sql в рамках стартовой темы и применительно использования процедур: мое мнение — смысла использовать сам linqtosql и в том числе и сам его маппер смысла не имеет, если схема строится только на процедурах, более того, в более-менее сложной системе, одно из требований которой скорость обработки данных, использовать linqtosql даже без использования процедур тоже не имеет смысла
Здравствуйте, DuШes, Вы писали:
DШ>я не говорил о проблемах с маппером, я вам уже объяснил, что маппер и дизайнер рассматриваю вместе, возможно поставил вас в заблуждение,и вот собственно невозможность его использования применительно к процедурам для построения схемы является той проблемой, которую пытался обозначить
В этом-то и ошибка маппер и дизайнер вполне себе независимые вещи. Например, маппер можно использовать если у вас есть только датаридер и вы хотите из него получить список объектов. Или сущности генерить не дизайнером, а T4-шаблоном.
L>>не надо менять предмет обсуждения. вы высказались про linq2sql-овский маппер, что он "ужос": L>>
L>+ маппиниг резалтсета хранимой процедуры на объекты.
L>>вот это и есть ужос, который превратится в будущем в еще более ужос, когда придется расширять классы или структуру таблиц...
L>>Что вы тут имели в виду конкретно маппер или все-таки весь linq2sql целиком?
DШ>не знаю как вы, но лично я не отделяю маппер и linq to sql data context designer и рассматриваю их как неделимое целое ...
Зачем их рассматривать вместе? Я этого не понимаю?
DШ>дык вот, маппер для процедур — его нет да в принципе теоретически быть не может, когда речь будет идти о возвращаемом датасете из нескольких таблиц...
не маппер для процедур невозможен, а невозможна генерация типизированного резалтсета для таких процедур.
тем не менее для таких процедур можно вполне успешно использовать маппер, смотри доку по IMultipleResults
DШ>в целом, если вы просто говорите что мол да, маппер свои задачи чисто по маппингу в/из базы/классы выполняет — то да, тут не соглашаться не с чем...это самое простое что есть забиндить поле из таблицы в соотвествующее свойство из класса,
А чего тогда было не него наезжать-то?
DШ>но использовать чисто маппер из всего linq to sql ради только маппера вообще теряет смысл — и на этом давайте закончим наше обсуждение именно маппера, а не в целом linq to sql
Нет, рано заканчивать. Мне надо убедиться, что вы в достаточной мере знаете возможности linq2sql-а (а не только его дизайнера). А там уже и закончим.
DШ>теперь в целом по linq to sql в рамках стартовой темы и применительно использования процедур: мое мнение — смысла использовать сам linqtosql и в том числе и сам его маппер смысла не имеет, если схема строится только на процедурах, более того, в более-менее сложной системе, одно из требований которой скорость обработки данных, использовать linqtosql даже без использования процедур тоже не имеет смысла
Только потому что дизайнер что-то не поддерживает, вы пишите все руками? Времени своего не жалко что-ли?
Здравствуйте, IB, Вы писали:
IB>Здравствуйте, gandjustas, Вы писали:
G>> В этом конкретном случае видимно никто и не собирался залить в процедуры для оптимизации, обычно их применяют только для инкапсуляции, view в этом плане гороздо выгоднее. IB>Проблема в том, что можно доинкапсулироваться до полной потери производительности.
Сделать хреново можно и с ХП.
G>>ИМХО нет разницы править 4 процедуры или вьюху и 3 триггера. IB>Править нет. А вот когда нужно понять что происходит или что-то поменять с предсказуемым результатом — процедуры рулят.
Это относительно. Я уже вполне привык работать с вьюхами и триггерами.
Главное чтобы каши не было, если делать, то все одинаково.
Здравствуйте, Tom, Вы писали:
G>>производительность системы — да, производительность программистов от этого сильно уменьшится. Tom>А можно аргументы?
Ну это вроде как очевидно.
Текстовые запросы тяжелее писать\пожжерживать, чем Linq, кроме того на каждое изменение выборки придется модифицировать целевую БД.
Здравствуйте, Lloyd, Вы писали:
L>В этом-то и ошибка маппер и дизайнер вполне себе независимые вещи. Например, маппер можно использовать если у вас есть только датаридер и вы хотите из него получить список объектов. Или сущности генерить не дизайнером, а T4-шаблоном. L>Зачем их рассматривать вместе? Я этого не понимаю? L>А чего тогда было не него наезжать-то?
такое ощущение, что у вас свой linqtosql и работаете вы не используя datacontext...
никто не наезжал на маппер, маппер в вашем понимании и самое понятие маппинг разные вещи, вы видимо говорите об определенных классах из system.data.linq, я же говорю о самом процессе организации связи данных из процедуры на свойства сгенерированных в схеме классов, и в данном случае преимуществ нет от использования linqtosql по сравнению с классическим использование Datareader и использованием рефлексии или же вы просто не можете их показать
L>Нет, рано заканчивать. Мне надо убедиться, что вы в достаточной мере знаете возможности linq2sql-а (а не только его дизайнера). А там уже и закончим.
Какие возможности, о чем вы говорите сейчас? об использовании IQueriable, об использовании system.data.linq.mapping? в чем вам надо убедиться, в том что вы взяли за основу классы из linqtosql, затачиваете их вручную путем кодирования классов под себя и считаете что используете в полной мере linqtosql — ну наверно в данном контексте можно сказать что используете, только стоило ли оно того? хотя бы сценарии использования чтоли приведите, в ыработаете через сгенерированный datacontext или же просто используете классы cfvjuj linqtosql, по сути реализовав свою сотственную реализацию DAL? ведь суть применения linqtosql и состояла, может я конечно и заблуждаюсь, чтобы максимально отодвинуть программиста от разработки этого слоя и использования сразу классов бизнесс-логики или нет?
L>Только потому что дизайнер что-то не поддерживает, вы пишите все руками? Времени своего не жалко что-ли?
времени мне своего не жалко, потому что такого рода orm мапперы пишутся за час, и широко используются ... вот только в качестве основного преимущества использоания linq-вского маппинга почему то считается именно сам дизайнер...
Здравствуйте, DuШes, Вы писали:
L>>В этом-то и ошибка маппер и дизайнер вполне себе независимые вещи. Например, маппер можно использовать если у вас есть только датаридер и вы хотите из него получить список объектов. Или сущности генерить не дизайнером, а T4-шаблоном. L>>Зачем их рассматривать вместе? Я этого не понимаю? L>>А чего тогда было не него наезжать-то?
DШ>такое ощущение, что у вас свой linqtosql и работаете вы не используя datacontext...
Linq2Sql у меня ровно тот же, что и у всех остальных.
DШ>никто не наезжал на маппер, маппер в вашем понимании и самое понятие маппинг разные вещи, вы видимо говорите об определенных классах из system.data.linq, я же говорю о самом процессе организации связи данных из процедуры на свойства сгенерированных в схеме классов, и в данном случае преимуществ нет от использования linqtosql по сравнению с классическим использование Datareader и использованием рефлексии или же вы просто не можете их показать
Я привел эти преимущства выше по ветке в виде списка. Преимуществ же речного маппинга или самописного маппинга через refelection вы почему-то не привели. Где они?
L>>Нет, рано заканчивать. Мне надо убедиться, что вы в достаточной мере знаете возможности linq2sql-а (а не только его дизайнера). А там уже и закончим. DШ>Какие возможности, о чем вы говорите сейчас? об использовании IQueriable, об использовании system.data.linq.mapping? в чем вам надо убедиться, в том что вы взяли за основу классы из linqtosql, затачиваете их вручную путем кодирования классов под себя и считаете что используете в полной мере linqtosql — ну наверно в данном контексте можно сказать что используете, только стоило ли оно того? хотя бы сценарии использования чтоли приведите, в ыработаете через сгенерированный datacontext или же просто используете классы cfvjuj linqtosql, по сути реализовав свою сотственную реализацию DAL? ведь суть применения linqtosql и состояла, может я конечно и заблуждаюсь, чтобы максимально отодвинуть программиста от разработки этого слоя и использования сразу классов бизнесс-логики или нет?
Что за привычка съезжать в сторону. Мы обсуждаем не мои способы работы, а недостатки linq2sql-а, с которыми вы сталкиваетесь. Давайте закончим с обсуждением маппинга процедур, возвращающих несколько резалтсетов. А потом перейдем на длюбые другие интересующие вас темы. Ок?
L>>Только потому что дизайнер что-то не поддерживает, вы пишите все руками? Времени своего не жалко что-ли? DШ>времени мне своего не жалко, потому что такого рода orm мапперы пишутся за час, и широко используются ... вот только в качестве основного преимущества использоания linq-вского маппинга почему то считается именно сам дизайнер...
Почему вы так выбрасываете ответы на вопросы, которые вы ставили? Вам чем-то не удовлетворил предложенный IMultipleResults?
Здравствуйте, Lloyd, Вы писали:
L>Я привел эти преимущства выше по ветке в виде списка. Преимуществ же речного маппинга или самописного маппинга через refelection вы почему-то не привели. Где они?
вы их спрашивали?
те преимущества, которые вы привели:
1. Он есть
2. качественно оттестирован толпой тестеров в микрософте
3. по нему есть документация
4. если с ним возникнет какая-то проблема, существует большое кол-во людей, которые его использовали в очень разных сценариях и они смогут мне помочь
вот эти? вам самому не смешно?
Почему вы выбрасываете или просто игнорируете мои ответы? я повторюсь, то что вы заточили классы linq под себя, имеет право на существование, но не дает ровно никаких преимуществ...
L>Почему вы так выбрасываете ответы на вопросы, которые вы ставили? Вам чем-то не удовлетворил предложенный IMultipleResults?
никто в сторону не съезжал все о чем вы говорите это и есть напильник и по сути свой уже самописный dal, ну давайте здраво рассуждать, внесение изменений в сгенерированные классы, написание своих кастомных классов для обертки результатов процедур, трекинг вручную, ну давайте сюда впишем реализацию IMultipleResults для датасетов — вы считаете, что это дало вам преимущество какое-то? вы не написали свой слой для работы с базой? это вам так реально помогает и уменьшает трудозатраты?
задача linqtosql была в первую очередь генерация классов на основе предложенной схемы базы данных, он должен был забрать на себя эти обязанности, не вы...
Re[20]: LINQ vs Store Procedure
От:
Аноним
Дата:
19.03.09 19:55
Оценка:
Здравствуйте, DuШes, Вы писали:
DШ>задача linqtosql была в первую очередь генерация классов на основе предложенной схемы базы данных, он должен был забрать на себя эти обязанности, не вы...
imho дизайнер (генератор классов, маппинга) это мизер в linq2sql, хоть он и позволяет быстро что-то сделать.
в nhibernate вообще этого нет, есть простенький тул по генерации простых классов-шаблонов по схеме маппинга, но многие считают что это неплохой ORM.
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, DuШes, Вы писали:
DШ>>задача linqtosql была в первую очередь генерация классов на основе предложенной схемы базы данных, он должен был забрать на себя эти обязанности, не вы...
А>imho дизайнер (генератор классов, маппинга) это мизер в linq2sql, хоть он и позволяет быстро что-то сделать. А>в nhibernate вообще этого нет, есть простенький тул по генерации простых классов-шаблонов по схеме маппинга, но многие считают что это неплохой ORM.
если вкратце, скажем, есть задача по созданию dal, в рамках обсуждения считаем, что используем процедуры (не напрямую таблицы), что мне предлагает linqtosql:
1. написать класс логики, который будет являться отображением полей из возвращаемого набора нашей процедуры
2. атрибутивно показать, какое поле из рекордсета в какое свойство моего класса маппится
3. ну и ручной трекинг через аксессоры
вручную:
1. без изменения
2. получаю datareader, вручную заполняю нужные мне свойства
3. без изменения
все операции по удалению, сохранению сводятся по сути к вызову процедуры что в первом что во втором случае...
в случае прямого маппинга из таблиц на классы — тут преимущество налицо, полная мощь генератора, пара секунд и все классы сгенерированы, спорить не очем..один минус — нет обратной связи из классов в структуру базы, скажем, в devexpress xpo это есть, и не нужно задумываться о ручном добавлении поля обратно в базу
я не спорю, linqtosql очень мощный инструмент и для определенного круга задач его использование более чем оправдано, но когда дело доходит до чуть более сложных схем маппинга, возникают трудозатраты, сравнимые с написанием своего собственного dal...
Здравствуйте, DuШes, Вы писали:
L>>Я привел эти преимущства выше по ветке в виде списка. Преимуществ же речного маппинга или самописного маппинга через refelection вы почему-то не привели. Где они?
DШ>вы их спрашивали?
Считайте, что спрашиваю сейчас.
DШ>те преимущества, которые вы привели: DШ>
DШ>1. Он есть
DШ>2. качественно оттестирован толпой тестеров в микрософте
DШ>3. по нему есть документация
DШ>4. если с ним возникнет какая-то проблема, существует большое кол-во людей, которые его использовали в очень разных сценариях и они смогут мне помочь
DШ>вот эти? вам самому не смешно?
Нет, ничуть. Я ведь не знаю функциональности вашего маппера, поэтому не могу в качестве преимуществ приводить функциональность, приходится ограничиваться теми, по которым самописный код по-любому проигрывает. Если приведете описание функционала вашего маппера, тогда можно будет сравнивать их.
DШ>Почему вы выбрасываете или просто игнорируете мои ответы?
Извините, если это действительно произошло. Если я что-то пропустил, укажите что именно, по возможности постараюсь исправить эту ошибку
DШ>я повторюсь, то что вы заточили классы linq под себя, имеет право на существование, но не дает ровно никаких преимуществ...
Я не затачивал классы linq2sql под себя, совсем не затачивал. С чего вы взяли, что я что-то где-либо затачивал?
L>>Почему вы так выбрасываете ответы на вопросы, которые вы ставили? Вам чем-то не удовлетворил предложенный IMultipleResults?
DШ>никто в сторону не съезжал все о чем вы говорите это и есть напильник и по сути свой уже самописный dal, ну давайте здраво рассуждать, внесение изменений в сгенерированные классы,
Ссылку, ни о каких внесениях изменений я не писал, даже в мыслях не было.
DШ>написание своих кастомных классов для обертки результатов процедур,
Совсем не обязательно писать эту обертку, если считаете, что она не нужна. Просто почитайте что такое IMultipleResults. И вопросы отпадут сами собой.
DШ>трекинг вручную,
Опять же, ссылку
DШ>ну давайте сюда впишем реализацию IMultipleResults для датасетов
Во-первых, не "для датасетов", а "для процедур возвращающих несколько резалтсетов"
А во-вторых, не реализация, а использование функционала, который уже входит в состав linq2sql, в том числе имеется поддержка со стороны дизайнера.
DШ>- вы считаете, что это дало вам преимущество какое-то? вы не написали свой слой для работы с базой? это вам так реально помогает и уменьшает трудозатраты?
Не написал ни строчки, в том-то и фишка. Весь функционал идет из коробки.
DШ>задача linqtosql была в первую очередь генерация классов на основе предложенной схемы базы данных, он должен был забрать на себя эти обязанности, не вы...
Это вообще ни разу не задача Linq2Sql — это задача дизайнера Linq2Sql, не надо путать эти две вещи, а то вы так докатетесь до того, что станете утверждать, что то, что генерит тот же SQLMetal — это не Linq2Sql
Здравствуйте, DuШes, Вы писали:
DШ>если вкратце, скажем, есть задача по созданию dal, в рамках обсуждения считаем, что используем процедуры (не напрямую таблицы), что мне предлагает linqtosql: DШ>1. написать класс логики, который будет являться отображением полей из возвращаемого набора нашей процедуры
не класс логики, а даных и не написать, а воспользоваться дизайнером.
DШ>2. атрибутивно показать, какое поле из рекордсета в какое свойство моего класса маппится
Нужно, но опять же в дизайнере.
DШ>3. ну и ручной трекинг через аксессоры
Никакого ручного трекинга. Дизайнер сгенерит нужный код сам.
DШ>вручную: DШ>1. без изменения
Не совсем (см. выше).
DШ>2. получаю datareader, вручную заполняю нужные мне свойства DШ>3. без изменения
Не совсем (см. выше).
DШ>все операции по удалению, сохранению сводятся по сути к вызову процедуры что в первом что во втором случае...
Не совсем. В первом способе ты сможешь в дизайнере указать INSERT/UPDATE/DELETE-процедуры для созданного класса данных и переложить функционал по вызову этих процедур на плечи Linq2Sql-а. С твоей стороны вся работа сведется к вызову context.SubmitChanges()
DШ>в случае прямого маппинга из таблиц на классы — тут преимущество налицо, полная мощь генератора, пара секунд и все классы сгенерированы, спорить не очем..один минус — нет обратной связи из классов в структуру базы, скажем, в devexpress xpo это есть, и не нужно задумываться о ручном добавлении поля обратно в базу
Этот недостаток имеется, но при должной дисциплине разработки с ним можно жить. Лучше бы его не было, но что делать.
DШ>я не спорю, linqtosql очень мощный инструмент и для определенного круга задач его использование более чем оправдано, но когда дело доходит до чуть более сложных схем маппинга, возникают трудозатраты, сравнимые с написанием своего собственного dal...
еще раз, как я понимал, беседа изначально велась в конктексте использования процелур в рамках linqtosql, собственно и тема так называется, я пытался вам доказать, что если речь идет о переходе на использование процедур, то смысла применять linqtosql просто нет, а стоит задуматься о написании своей orm или рассматривать другие решения, о минусах и плюсах самого linqtosql вроде бы тоже говорили..
L>>>Я привел эти преимущства выше по ветке в виде списка. Преимуществ же речного маппинга или самописного маппинга через refelection вы почему-то не привели. Где они? DШ>>вы их спрашивали? L>Считайте, что спрашиваю сейчас.
ну как минимум обратное отображение в базу данных, в идеале я вообще не должен вносить изменений в базе, если уж использовать некую orm, то вообще на задумываясь о структуре базы, это есть и задача полноценной orm, и полноценный трекинг, лишенный вероятности прости физически забыть дернуть событие из аксессоров...
DШ>>те преимущества, которые вы привели: DШ>>
DШ>>1. Он есть
DШ>>2. качественно оттестирован толпой тестеров в микрософте
DШ>>3. по нему есть документация
DШ>>4. если с ним возникнет какая-то проблема, существует большое кол-во людей, которые его использовали в очень разных сценариях и они смогут мне помочь
DШ>>вот эти? вам самому не смешно? L>Нет, ничуть. Я ведь не знаю функциональности вашего маппера, поэтому не могу в качестве преимуществ приводить функциональность, приходится ограничиваться теми, по которым самописный код по-любому проигрывает. Если приведете описание функционала вашего маппера, тогда можно будет сравнивать их.
в качестве преимущества вы приводите то что он есть? есть документация? не спорю, наверно это действительно сильные стороны...свои доводы в пользу написания своего mapping dal привел выше
Задумываться об этом действительно не стоит, т.к. эту проблему вполне себе решает Linq2Sql-овский дизайнер.
...
Конечно, у меня не возникало таких проблем. У нас на проекте есть сложившаяся процедура внесения изменений в схему базы, благодаря которой нет необходимости "убивать всю схему и генерировать снова". Это экономит кучу времени. Рекомендую вам с коллегами сесть как-нить вечерком с пивком и решить раз и навсегда, как по-правильному вносить изменения.
...
Никто никуда не кричит. Тот, кто изменяет схему, обязан изменить и соответствующие entity. Самый простой способ — это внести это изменение вручную в dbml.
...
...
теперь в целом по linq to sql в рамках стартовой темы и применительно использования процедур: мое мнение — смысла использовать сам linqtosql и в том числе и сам его маппер смысла не имеет, если схема строится только на процедурах, более того, в более-менее сложной системе, одно из требований которой скорость обработки данных, использовать linqtosql даже без использования процедур тоже не имеет смысла
Только потому что дизайнер что-то не поддерживает, вы пишите все руками? Времени своего не жалко что-ли?
где я писал, что пишется все руками?
если вернемся в начало, то началось все с данного моего ответа, собственно я остался пока при своем мнении о наличии "ужоса" в процессе как разработки так и сопровождения схемы на основе процедур
L>+ маппиниг резалтсета хранимой процедуры на объекты.
вот это и есть ужос, который превратится в будущем в еще более ужос, когда придется расширять классы или структуру таблиц...
к тому же, самое плохое в linq to sql это то, что нет обратного маппинга из классов схемы в базу данных...в том же самом DX XPO эта проблема решена (не сочтите за рекламу )
еще раз, те минусы которые я увидел:
нужно свойство — добавляем поле в таблицу, обеспечиваем синхронизацию путем выставления атрибутов, вносим код для трекинга в аксессоры, и это мы еще не рассматривали варианты, когда меняется тип данных...причем процесс контролируется только разработчиком, представляю себе сложности, которые могут возникнуть в случае необходимости поддержания версионности базы данных..
для процедур вообще ручное кодирование классов-врапперов и необходимоть поддержания как самого кода процедуры, так и самого класса в синхронном состоянии, потому что ну нет возможности отселдить изменения в коде процедуры и наложить их обратно на класс не говоря уж об обратном процессе..
Здравствуйте, gandjustas, Вы писали:
G>Здравствуйте, Tom, Вы писали:
G>>>производительность системы — да, производительность программистов от этого сильно уменьшится. Tom>>А можно аргументы? G>Ну это вроде как очевидно. G>Текстовые запросы тяжелее писать\пожжерживать, чем Linq, кроме того на каждое изменение выборки придется модифицировать целевую БД.
В упор непонимаю почему запросы SQL тяжелее писать чем LINQ. Как раз SQL (TSQL) обладает всей мощью для работы с БД, в отличии от линка.
Ну и второй аргумент вообще непонятен. зачем целевую БД модифицировать, почему, непонятно....
L>Совсем не обязательно. Мы на одном проекте использовали типизированые обертки над хранимками (свой кастом тул), внутри которого вполне себе удачно использовался ADO.NET
Ну и правильно, кастом тул я не рассматривал.вариант с кастом тулом который строит враперы над сторами и запросами вообще нравится больше линка.
J>>>1. LINQ to SQL, завязаный только на хранимые процедуры — это "LINQ to SQL" без слова "LINQ". Что там собственно останется-то хорошего, если оттуда убрать запросы? Tom>>останется compile time проверки вызова стор. J>Скорее строго-типизированная обертка, чем полноценная проверка. Проверять что параметры хранимке переданы правильно, оно не будет. И даже что она на самом деле есть в базе — не проверит.
Строго типизированная обёртка как раз и есть то, что ОЧЕНЬ необходимо при работе с БД. По поводу того, что на самом деле есть в базе — это вопрос того как устроен билд. Если у вас линк related код генерится в ходе билда, а не один раз статически из студии, то у вас очень хорошая гарантия что ваш C# синхронизирован с БД.
J>Я имел ввиду что перенос сгенеренных линкой запросов в хранимки не даст прироста. Но можно и переписать все, конечно, с полной уверенностью что "уж я-то шарю в базах, уж я-то всяко сделаю быстрее, чем тупой генератор". Но это обратно по поводу самодуров и кретинов. Далеко не факт что это даст прирост чистыми (см. "преждевременная оптимизация" и "5% кода занимают 95% времени").
Не надо называть всех идиотами, критинами и самодурами. Это не добавляет сообщениям смысла.
Тупой генератор, может сгенерировать человеческий запрос для простых случаев. В реальных системах, когда запросы становятся сложными, написать их на линке вообще невозможно, а тем более написать их оптимально. TSQL развивался десятилетиями и специально заточен для работы с бд. Вот и используете его для работы с БД. А хранимки для того, что бы эти сложные операции/запросы оптимизировать и поддерживать.
Tom>>Работать с хранимкапми на порядок удобнее, намного проще например отлаживать план выполнения. J>Работать с ассемблером тоже было бы удобнее, если бы все занимались исключительно оптимизацией. J>Минусов у хранимок навалом. Мне они очевидны и здесь сто раз уже обсуждались. Расписать основные?
Распиши конечно
L>Конечно, у меня не возникало таких проблем. У нас на проекте есть сложившаяся процедура внесения изменений в схему базы, благодаря которой нет необходимости "убивать всю схему и генерировать снова". Это экономит кучу времени. Рекомендую вам с коллегами сесть как-нить вечерком с пивком и решить раз и навсегда, как по-правильному вносить изменения.
О, а можно пару слов, про процедуру внесения изменений в схему?
TK>Почитайте тут: http://msdn.microsoft.com/ru-ru/library/ms181055.aspx TK>В остальном, надо исходить из того, что SQL Server хранит только исходный код хранимых процедур и триггеров. При выполнении хранимой процедуры или триггера в первый раз исходный код компилируется в план выполнения. т.е. разница только в том, где будет хранится "текст" запросов. в случае с хранимыми процедурами (особенно если их тысячи) вы "усложняете" себе поддержку вашего решения.
По сабжу. Ado.NET Team продолжает традиции МС в разработке фреймворков для доступа к данным: вместо того, чтобы довести хоть одну технологию до ума, они вечно бросаются из крайности в крайность — то у нас рулит disconnected approach и датасеты, то нифига, бизнесь не выживет без ормапперов с поддержкой наследования и статически верифицируемых запросов к СУБД.
Если не секрет, о каких типах приложений вы спорите? И EF, И Linq2Sql неудобны для написания data-driven desktop clients по куче причин. Во-первых отсутствие disconnected-режима (только давайте не будем говорить про Sql Compact и репликацию с главным сервером — это разные сценарии). Во-вторых — грабли с биндингом, загрузкой графа объектов и регистрацией их в контексте (особенно через хранимки). В третьих — невозможность глобальной валидации на уровне контекста. Либо работаем исключительно через воспомогательные методы (биндинг идёт лесом), либо смиряемся с тем, что некорректные данные обнаруживаются только сервером при submit changes. Я говорю не о тривиальных проверках, которые вполне осуществимы через геттеры/сеттеры, а о проверках, которые необходимо делать при изменении контекста (эдакий аналог событий RowChanging у DataTable).
Здравствуйте, DuШes, Вы писали:
DШ>еще раз, как я понимал, беседа изначально велась в конктексте использования процелур в рамках linqtosql, собственно и тема так называется, я пытался вам доказать, что если речь идет о переходе на использование процедур, то смысла применять linqtosql просто нет, а стоит задуматься о написании своей orm или рассматривать другие решения, о минусах и плюсах самого linqtosql вроде бы тоже говорили..
L>>>>Я привел эти преимущства выше по ветке в виде списка. Преимуществ же речного маппинга или самописного маппинга через refelection вы почему-то не привели. Где они? DШ>>>вы их спрашивали? L>>Считайте, что спрашиваю сейчас.
DШ>ну как минимум обратное отображение в базу данных, в идеале я вообще не должен вносить изменений в базе, если уж использовать некую orm, то вообще на задумываясь о структуре базы, это есть и задача полноценной orm, и полноценный трекинг, лишенный вероятности прости физически забыть дернуть событие из аксессоров...
Вариант с Linq2Sql-м + сущности сгенерированные дизайнером отвечает этим критериям.
DШ>>>те преимущества, которые вы привели: DШ>>>
DШ>>>1. Он есть
DШ>>>2. качественно оттестирован толпой тестеров в микрософте
DШ>>>3. по нему есть документация
DШ>>>4. если с ним возникнет какая-то проблема, существует большое кол-во людей, которые его использовали в очень разных сценариях и они смогут мне помочь
DШ>>>вот эти? вам самому не смешно? L>>Нет, ничуть. Я ведь не знаю функциональности вашего маппера, поэтому не могу в качестве преимуществ приводить функциональность, приходится ограничиваться теми, по которым самописный код по-любому проигрывает. Если приведете описание функционала вашего маппера, тогда можно будет сравнивать их.
DШ>в качестве преимущества вы приводите то что он есть? есть документация? не спорю, наверно это действительно сильные стороны...
То, что вы описали, уже есть в Linq2Sql, так что необходимости-таки нет.
DШ>свои доводы в пользу написания своего mapping dal привел выше
нет, выше вы привели доводы по поводу того, что вы считаете "полноценной orm". не подменяйте понятия. перечитывайте ответ перед тем как нажать "Отправить"
DШ>
DШ>Задумываться об этом действительно не стоит, т.к. эту проблему вполне себе решает Linq2Sql-овский дизайнер.
DШ>...
DШ>Конечно, у меня не возникало таких проблем. У нас на проекте есть сложившаяся процедура внесения изменений в схему базы, благодаря которой нет необходимости "убивать всю схему и генерировать снова". Это экономит кучу времени. Рекомендую вам с коллегами сесть как-нить вечерком с пивком и решить раз и навсегда, как по-правильному вносить изменения.
DШ>...
DШ>Никто никуда не кричит. Тот, кто изменяет схему, обязан изменить и соответствующие entity. Самый простой способ — это внести это изменение вручную в dbml.
DШ>...
DШ>...
DШ>теперь в целом по linq to sql в рамках стартовой темы и применительно использования процедур: мое мнение — смысла использовать сам linqtosql и в том числе и сам его маппер смысла не имеет, если схема строится только на процедурах, более того, в более-менее сложной системе, одно из требований которой скорость обработки данных, использовать linqtosql даже без использования процедур тоже не имеет смысла
DШ>Только потому что дизайнер что-то не поддерживает, вы пишите все руками? Времени своего не жалко что-ли?
DШ>где я писал, что пишется все руками?
DШ>если вернемся в начало, то началось все с данного моего ответа, собственно я остался пока при своем мнении о наличии "ужоса" в процессе как разработки так и сопровождения схемы на основе процедур
Я понял, что вы остались при своем мнении, но не понял почему
DШ>
L>>+ маппиниг резалтсета хранимой процедуры на объекты.
DШ>вот это и есть ужос, который превратится в будущем в еще более ужос, когда придется расширять классы или структуру таблиц...
DШ>к тому же, самое плохое в linq to sql это то, что нет обратного маппинга из классов схемы в базу данных...в том же самом DX XPO эта проблема решена (не сочтите за рекламу )
DШ>еще раз, те минусы которые я увидел: DШ>нужно свойство — добавляем поле в таблицу, обеспечиваем синхронизацию путем выставления атрибутов, вносим код для трекинга в аксессоры, и это мы еще не рассматривали варианты, когда меняется тип данных...
Нет, не совсем так. Добавляем поле в дизайнере, нажимаем Save. Все, алгоритм закончился. При изменении типа все ровно то же самое.
DШ>причем процесс контролируется только разработчиком, представляю себе сложности, которые могут возникнуть в случае необходимости поддержания версионности базы данных..
Это понятия ортогональное к Linq2Sql-у, версионность базы тут никак не повлияет.
DШ>для процедур вообще ручное кодирование классов-врапперов и необходимоть поддержания как самого кода процедуры, так и самого класса в синхронном состоянии, потому что ну нет возможности отселдить изменения в коде процедуры и наложить их обратно на класс не говоря уж об обратном процессе..
Ровно то же самое вы будете делать и в своем продходе. Но в вашем подходе вам еще придется реализовывать маппинг. Где обещанное преимущество?
P.S. В своем предыдущем сообщении я попросил привести ссылки на мои сообщения, где я якобы: предлагал вручную менять сгенерированный код и реализовывать трекинг вручную. Не могли бы вы потрудиться и все-таки найти сообщения, где я все это предлагал? Спасибо.
Здравствуйте, Tom, Вы писали:
L>>Совсем не обязательно. Мы на одном проекте использовали типизированые обертки над хранимками (свой кастом тул), внутри которого вполне себе удачно использовался ADO.NET Tom>Ну и правильно, кастом тул я не рассматривал.вариант с кастом тулом который строит враперы над сторами и запросами вообще нравится больше линка.
Нет, этот вариант хуже линка, уверяю вас. Маппинг придется реализовывать в ручную. Хотя кому-то это очень нравится (DuШes).
Здравствуйте, Tom, Вы писали:
Tom>А в чём усложнение?
В том, что все запросы из кода надо каким-то неочевидным способом оборачивать в хранимки. Я не знаю готовых инструментов для этого. И даже с использованием инструментов считаю это излишним усложнением. При поддержке придется вместо linq запроса в коде править хранимку, какой выигрыш мы получаем от линка в данной ситуации? Также усложняем контроль версий или деплоинг приложения.
Здравствуйте, Lloyd, Вы писали:
L>Здравствуйте, Tom, Вы писали:
L>>>Совсем не обязательно. Мы на одном проекте использовали типизированые обертки над хранимками (свой кастом тул), внутри которого вполне себе удачно использовался ADO.NET Tom>>Ну и правильно, кастом тул я не рассматривал.вариант с кастом тулом который строит враперы над сторами и запросами вообще нравится больше линка.
L>Нет, этот вариант хуже линка, уверяю вас. Маппинг придется реализовывать в ручную. Хотя кому-то это очень нравится (DuШes).
:-D по-моему, вы уж както совсем пререходите на личности...и где я об этом говорил, что вручную? я говорил о том, что проще написать под свои цели свой dal нежели применять linqtosql + напильник в сценариях с применением хранимок...
и вообще само понятие "маппинг вручную" — что вы под этим понимаете? чем так сильно отличается использование атрибутов хотя бы отклассической модели datareader, уж даже не рассматриваем свои orm с применением свой кастомной декларативности в виде использования атрибутов?
А мне это напоминает странную особенность некоторых программистов, для которых легче написать свой тул, а не изучить существующий. Хотя существующий и покрывает все их потребности. Не понимаю я этого.
S>По сабжу. Ado.NET Team продолжает традиции МС в разработке фреймворков для доступа к данным: вместо того, чтобы довести хоть одну технологию до ума, они вечно бросаются из крайности в крайность — то у нас рулит disconnected approach и датасеты, то нифига, бизнесь не выживет без ормапперов с поддержкой наследования и статически верифицируемых запросов к СУБД.
EF вроде как поддерживает то ли disconnected entities, то ли контекст, так что тут все-таки не "бросаются из крайности в крайность", а довольно-таки поседовательнл.
S>Если не секрет, о каких типах приложений вы спорите? И EF, И Linq2Sql неудобны для написания data-driven desktop clients по куче причин. Во-первых отсутствие disconnected-режима (только давайте не будем говорить про Sql Compact и репликацию с главным сервером — это разные сценарии).
EF поддерживает, вроде.
S>Во-вторых — грабли с биндингом, загрузкой графа объектов и регистрацией их в контексте (особенно через хранимки).
А что с этим не так? Я просто не совсем в курсе.
S>В третьих — невозможность глобальной валидации на уровне контекста. Либо работаем исключительно через воспомогательные методы (биндинг идёт лесом), либо смиряемся с тем, что некорректные данные обнаруживаются только сервером при submit changes. Я говорю не о тривиальных проверках, которые вполне осуществимы через геттеры/сеттеры, а о проверках, которые необходимо делать при изменении контекста (эдакий аналог событий RowChanging у DataTable).
У Linq2Sql-овских сущностей точно есть аналог RowChanging, даже что-то с валидацией есть.
S>Плохие они все
Здравствуйте, Tom, Вы писали:
Tom>В упор непонимаю почему запросы SQL тяжелее писать чем LINQ. Как раз SQL (TSQL) обладает всей мощью для работы с БД, в отличии от линка.
Потому, что мы теряем большинство вкусностей линка — строгую типизацию в запросе, возможность конструировать запрос на лету уточняя критерии, писать запрос на том же языке, что и остальную логику.
Tom>Ну и второй аргумент вообще непонятен. зачем целевую БД модифицировать, почему, непонятно....
Ее в любом случае надо модифицировать. Рекомпиляции программы уже недостаточно для запуска.
L>P.S. В своем предыдущем сообщении я попросил привести ссылки на мои сообщения, где я якобы: предлагал вручную менять сгенерированный код и реализовывать трекинг вручную. Не могли бы вы потрудиться и все-таки найти сообщения, где я все это предлагал? Спасибо.
вы что в упор не видите? еще раз, мы говорим о процедурах или о чем?
Никто никуда не кричит. Тот, кто изменяет схему, обязан изменить и соответствующие entity. Самый простой способ — это внести это изменение вручную в dbml.
не маппер для процедур невозможен, а невозможна генерация типизированного резалтсета для таких процедур.
тем не менее для таких процедур можно вполне успешно использовать маппер, смотри доку по IMultipleResults
Этот недостаток имеется, но при должной дисциплине разработки с ним можно жить. Лучше бы его не было, но что делать.
вообщем, как я понимаю, ваш linqtosql дизайнер, именно ваш, потому что мой не умеет, настолько умный, что понимает логику в хранимых процедурах и за вас генерирует классы-врапперы над результати работы хранимки...или как?
Здравствуйте, DuШes, Вы писали:
Tom>>>Ну и правильно, кастом тул я не рассматривал.вариант с кастом тулом который строит враперы над сторами и запросами вообще нравится больше линка.
L>>Нет, этот вариант хуже линка, уверяю вас. Маппинг придется реализовывать в ручную. Хотя кому-то это очень нравится (DuШes). DШ>:-D по-моему, вы уж както совсем пререходите на личности...
А вам разве это не нравится? Зачем вы тогда это делаете?
DШ>и где я об этом говорил, что вручную? я говорил о том, что проще написать под свои цели свой dal нежели применять linqtosql + напильник в сценариях с применением хранимок...
Для меня это и есть вручную. Вручную педалить кучу кода, когда уже есть готовые фреймворки.
DШ>и вообще само понятие "маппинг вручную" — что вы под этим понимаете? чем так сильно отличается использование атрибутов хотя бы отклассической модели datareader, уж даже не рассматриваем свои orm с применением свой кастомной декларативности в виде использования атрибутов?
Здравствуйте, DuШes, Вы писали:
DШ>Здравствуйте, Lloyd, Вы писали:
L>>P.S. В своем предыдущем сообщении я попросил привести ссылки на мои сообщения, где я якобы: предлагал вручную менять сгенерированный код и реализовывать трекинг вручную. Не могли бы вы потрудиться и все-таки найти сообщения, где я все это предлагал? Спасибо.
DШ>вы что в упор не видите? еще раз, мы говорим о процедурах или о чем?
Да, я в упор не вижу, где я предлагаю вручную "менять сгенерированный код" и "реализовывать трекинг вручную". Можно конкретный цитаты по первому и по второму отдельно.
DШ>
DШ>Никто никуда не кричит. Тот, кто изменяет схему, обязан изменить и соответствующие entity. Самый простой способ — это внести это изменение вручную в dbml.
DШ>не маппер для процедур невозможен, а невозможна генерация типизированного резалтсета для таких процедур.
DШ>тем не менее для таких процедур можно вполне успешно использовать маппер, смотри доку по IMultipleResults
DШ>Этот недостаток имеется, но при должной дисциплине разработки с ним можно жить. Лучше бы его не было, но что делать.
DШ>вообщем, как я понимаю, ваш linqtosql дизайнер, именно ваш,
Он не мой, он микрософта.
DШ>потому что мой не умеет, настолько умный, что понимает логику в хранимых процедурах
Ссылку, где я такое говорил.
DШ>и за вас генерирует классы-врапперы над результати работы хранимки...
Здравствуйте, Spender, Вы писали:
S>Если бы я все это умел У нас есть человек специальный для этого. Он полностью занимается БД на стороне SQL сервера. Может даже оптимизирует что-то там. Но вряд ли. S>Спасибо за совет. Попробую все это рассказать шефу.
А ты научись. Во-первых там ничего сложного нет. Во-вторых — это все нужно будет расшарить в конце-концов.
Советую действовать по такой схеме (все сказаное относится к MS SQL, я так понял вы его используете):
По поводу гипотезы с тормозным запросом:
— открой sql profiler, зацепись к своей базе. Погоняй свое приложение под ним, может быть какой-то определенный запрос занимает много времени. Просто смотри колонки с метриками на предмет аномально больших значений.
— если такой запрос есть — выцепляй его прямо из профайлера в management studio и смотри план запроса — включи в меню query/include actual execution plan, выполни запрос и план выведется. В плане запроса нет никакого матана: смотреть нужно прежде всего какие операции занимают больше всего времени и примерно прикидывать зачем это действие делает база. Например всякие "... scan(99%)" часто говорят о том, что просто индекса какого-нибудь не хватает и субд вынуждена делать перебор.
По поводу гипотезы с блокировками:
— почитай про блокировки и уровни изоляции в books online, или где-нибудь еще. Именно касательно sql-сервера.
— для освоения материала открываешь на какой-нибудь своей базе два окошка, запускаешь в них транзакции с различными уровнями изоляции, наблюдаешь блокировки в activity monitor. Как разберешься хотя бы как увидеть в activity monitor какой процесс что ждет и что заблокировал, может приступать к практике.
— нагружаешь свою систему и смотришь какой процесс подвисает, на каком запросе, какая блокировка ему мешает, кто ее поставил.
Могут еще быть причины, но это — две основные. Если дело действительно в базе.
Здравствуйте, Lloyd, Вы писали:
[...]
объективности похоже ждать не приходится, особенно когда на вопрос тебе приходит встречный вопрос
ps: справедливости ради, на личности я не переходил, не "ты"кал и не хамил, более того, еще более убеждаюсь в том..
не поможет, уверяю тебя.
Чего-чего? Еще раз и помедленнее.
А чего тогда было не него наезжать-то?
Нет, рано заканчивать. Мне надо убедиться, что вы в достаточной мере знаете возможности linq2sql-а (а не только его дизайнера). А там уже и закончим.
Только потому что дизайнер что-то не поддерживает, вы пишите все руками? Времени своего не жалко что-ли?
Здравствуйте, Tom, Вы писали:
L>>Конечно, у меня не возникало таких проблем. У нас на проекте есть сложившаяся процедура внесения изменений в схему базы, благодаря которой нет необходимости "убивать всю схему и генерировать снова". Это экономит кучу времени. Рекомендую вам с коллегами сесть как-нить вечерком с пивком и решить раз и навсегда, как по-правильному вносить изменения. Tom>О, а можно пару слов, про процедуру внесения изменений в схему?
Да я тут ничего особо умного не скажу, просто здравый смысл: изменения, вносимые одним разработчиком, не должны мешать работать другому.
Поэтому желательно чтобы у каждого разработчика была своя база и разработка велась на ней. При выкладывании в сорс-контрол должны одноврененно выкладываться скрипты для базы и изменения в сущностях.
Если отдельные базы по каким-то причинам невозможно использовать, то разработчик должен максимально минимизировать время, когда база в рассогласованном состоянии с кодом.
Здравствуйте, Lloyd, Вы писали:
L>Да, я в упор не вижу, где я предлагаю вручную "менять сгенерированный код" и "реализовывать трекинг вручную". Можно конкретный цитаты по первому и по второму отдельно.
Никто никуда не кричит. Тот, кто изменяет схему, обязан изменить и соответствующие entity. Самый простой способ — это внести это изменение вручную в dbml.
не маппер для процедур невозможен, а невозможна генерация типизированного резалтсета для таких процедур.
тем не менее для таких процедур можно вполне успешно использовать маппер, смотри доку по IMultipleResults
Этот недостаток имеется, но при должной дисциплине разработки с ним можно жить. Лучше бы его не было, но что делать.
дизайнером или не дизайнером суть не меняется — это и есть вручную
L>Ссылку, где я такое говорил. L>Ссылку, где я такое говорил.
вы каждое слово будете вырывать из контекста?
вопрос был:
вообщем, как я понимаю, ваш linqtosql дизайнер, именно ваш, потому что мой не умеет, настолько умный, что понимает логику в хранимых процедурах и за вас генерирует классы-врапперы над результати работы хранимки...или как?
просто поделитесь опытом ну как вы работаете с хранимками, пока только слова в защиту того, какой маппер хороший и какие есть возможности в linqtosql, просто из контекста я понял, что у вас все так хорошо, что вы и дизайнер используете и маппинг из процедуры на классы и их автогенерацию...
ps: не подумайте плохо, ведь реально просто интересно, может быть действительно говорю за себя я не умею его готовить?
L>Нет, этот вариант хуже линка, уверяю вас. Маппинг придется реализовывать в ручную. Хотя кому-то это очень нравится (DuШes).
Я предпологал, что тул так же генерирует набор классов, на которые мапятся вызовы стор. Или у вас это не так?
Ещё раз всем спасибо! Тема я смотрю актуальная
Из всего вышеизложенного я понял, что хранимки вместо LINQ не решат проблемы, так как сейчас в текущей системе, которая "неотвечает" используется Reader, а он по сути самый быстрый способ достучаться до БД. Проблема в архитектуре. Индексов, как я понял у нас вообще нет %)
В общем будем вызывать специалиста. Кстати, нет никого желающего? Мы находимся в Миссиссаге, Онтарио, Канада.
S>В общем будем вызывать специалиста. Кстати, нет никого желающего? Мы находимся в Миссиссаге, Онтарио, Канада.
А климат у вас какой? Влажно? И летом/замой какая температура?
Если индексов нет то конечно всё будет тупить. Просто вам нужен человек более менее имебщий опыт разработки приложений связанных с БД.
Здравствуйте, Tom, Вы писали: Tom>А климат у вас какой? Влажно? И летом/замой какая температура?
Климат сухой. Зима была зимой. До -20. Сейчас от +15 до -5. Летом обещают тепло.
Tom>Если индексов нет то конечно всё будет тупить. Просто вам нужен человек более менее имебщий опыт разработки приложений связанных с БД.
Нужен. Шеф у нас такой Но он уже не разрабатывает, он зарабатывает
Здравствуйте, IB, Вы писали:
IB>Если есть DAL, то где конкретно находятся запросы для квалифицированного разработчика — фиолетово. Для стажеров — жестко, только хранимки.
Здравствуйте, DuШes, Вы писали:
DШ>Здравствуйте, Lloyd, Вы писали:
L>>Да, я в упор не вижу, где я предлагаю вручную "менять сгенерированный код" и "реализовывать трекинг вручную". Можно конкретный цитаты по первому и по второму отдельно.
DШ>
DШ>Никто никуда не кричит. Тот, кто изменяет схему, обязан изменить и соответствующие entity. Самый простой способ — это внести это изменение вручную в dbml.
DШ>не маппер для процедур невозможен, а невозможна генерация типизированного резалтсета для таких процедур.
DШ>тем не менее для таких процедур можно вполне успешно использовать маппер, смотри доку по IMultipleResults
DШ>Этот недостаток имеется, но при должной дисциплине разработки с ним можно жить. Лучше бы его не было, но что делать.
DШ>дизайнером или не дизайнером суть не меняется — это и есть вручную
Так вот, что вы имели в виду. Вы оказывается, dbml называете кодом, а автоматической генерацией называете процедуру перетаскивания всех таблиц в дизайнер или то, что получается при первоначальном создании dbml-я по базе. Я вас правильно понял?
Теперь что по поводу "реализовывать трекинг вручную"?
L>>Ссылку, где я такое говорил. L>>Ссылку, где я такое говорил.
DШ>вы каждое слово будете вырывать из контекста?
Для начала, если оставляете цитату собеседника, оставляйте достаточное кол-во текста, чтобы читающему можно было понять, о чем идет речь. Ок?
Во-вторых, цитату, где я говорил про то, что "мой" дизайнер "понимает логику в хранимых процедурах" и "генерирует классы-врапперы над результати работы хранимки", я хотел бы все-таки увидеть.
DШ>вопрос был: DШ>вообщем, как я понимаю, ваш linqtosql дизайнер, именно ваш, потому что мой не умеет, настолько умный, что понимает логику в хранимых процедурах и за вас генерирует классы-врапперы над результати работы хранимки...или как?
DШ>просто поделитесь опытом ну как вы работаете с хранимками, пока только слова в защиту того, какой маппер хороший и какие есть возможности в linqtosql, просто из контекста я понял, что у вас все так хорошо, что вы и дизайнер используете и маппинг из процедуры на классы и их автогенерацию...
Здравствуйте, Tom, Вы писали:
L>>Нет, этот вариант хуже линка, уверяю вас. Маппинг придется реализовывать в ручную. Хотя кому-то это очень нравится (DuШes). Tom>Я предпологал, что тул так же генерирует набор классов, на которые мапятся вызовы стор. Или у вас это не так?
Классы генерятся, если процедура возвращает 1 рекордсет. Если больше одного, надо самостоятельно указывать тип.
L>Здесь процедура CustOrderHistTwice возвращает 2 резалтсета.
L>Использовать во так:
L>
L>DataClasses1DataContext ctx = new DataClasses1DataContext();
L>var result = ctx.CustOrderHistTwice("CACTU");
L>foreach (var hist in result.GetResult<CustOrderHistResultEntry>())
L>{
L> Console.WriteLine(new { hist.ProductName, hist.Total });
L>}
L>Console.WriteLine("==============");
L>foreach (var hist in result.GetResult<CustOrderHistResultEntry>())
L>{
L> Console.WriteLine(new { hist.ProductName, hist.Total });
L>}
L>
L>И все.
L>Как видишь, никакой магии и правки руками. Только стандартный функционал.
давайте наверно уже закончим я понял что вы имеет ввиду, магия здесь в классах CustOrderHistResultEntry и в поддержке такиго рода в синхронном состоянии
Здравствуйте, DuШes, Вы писали:
L>>Как видишь, никакой магии и правки руками. Только стандартный функционал.
DШ>давайте наверно уже закончим
давайте для начала вы ответите на вопросы, которые вам были заданы. проявляйте уважение к собеседнику.
DШ>я понял что вы имеет ввиду, магия здесь в классах CustOrderHistResultEntry и в поддержке такиго рода в синхронном состоянии
Опишите свой вариант. Как вы поддерживаете синхронность кроме как руками? Я вариантов вообще не вижу. Более того, у меня есть подозрение, что это нельзя сделать атоматически всилу того, что sqlserver не возвращает схему резалтсетов, следующих за первым. Хотя по этому поводу я не на 100% уверен.
Здравствуйте, kenzo_u, Вы писали:
_>Почему фиолетово для квалифицированного разработчика и почему только хранимки для стажеров?
Потому что у опытного разработчика DAL будет в любом случае, а стажеру надо учиться запросы отделять, да и руку набивать в работе с базой. А то потом появляются разработчики, которые БД боятся как огня, не знают что с ней делать и только мифы всякие распространяют.. =)
Здравствуйте, Sinix, Вы писали:
S>Сорри, что вмешиваюсь, но получение схемы результсета хранимой процедуры — вполне выполнимая операция. Скажем, дадасет дизайне такое умеет.
Значит ошибался. А где можно посмотреть как оно работает?
L>Классы генерятся, если процедура возвращает 1 рекордсет. Если больше одного, надо самостоятельно указывать тип.
А больше одного и нафик не нужно обычно.
L>Значит ошибался. А где можно посмотреть как оно работает?
Ага, интересно особенно как оно будет работать если мы вдруг ему подсунем стору которая возвращает разные наборы при разных входных параметрах.
Здравствуйте, Tom, Вы писали:
L>>Классы генерятся, если процедура возвращает 1 рекордсет. Если больше одного, надо самостоятельно указывать тип. Tom>А больше одного и нафик не нужно обычно.
У всех разные сценарии.
Нафига все это нужно?!?! Если для того, чтобы получить 1 запись из базы вынимаются все!!! и потом из них уже возвращается одна. Либо я чего-то не понимаю. Ведь быстрее вытащить только то, что нам надо, чем потом искать?!?!
Здравствуйте, Lloyd, Вы писали:
L>Здравствуйте, DuШes, Вы писали:
L>>>Как видишь, никакой магии и правки руками. Только стандартный функционал.
DШ>>давайте наверно уже закончим
L>давайте для начала вы ответите на вопросы, которые вам были заданы. проявляйте уважение к собеседнику.
да о чем вы говорите, вы сами давно уже прекратили здесь http://rsdn.ru/forum/message/3335827.1.aspx
насчет ваших вопросов: L>Так вот, что вы имели в виду. Вы оказывается, dbml называете кодом, а автоматической генерацией называете процедуру перетаскивания всех таблиц в дизайнер или то, что получается при первоначальном создании dbml-я по базе. Я вас правильно понял?
dbml — да, именно тот код, а вы что подразумевали под классами-врапперами, о которых я уже устал писать ...
L>Теперь что по поводу "реализовывать трекинг вручную"?
насчет трекинга вручную, в вашем примере: L>
L>DataClasses1DataContext ctx = new DataClasses1DataContext();
L>var result = ctx.CustOrderHistTwice("CACTU");
L>foreach (var hist in result.GetResult<CustOrderHistResultEntry>())
L>{
L> Console.WriteLine(new { hist.ProductName, hist.Total });
L>}
L>Console.WriteLine("==============");
L>foreach (var hist in result.GetResult<CustOrderHistResultEntry>())
L>{
L> Console.WriteLine(new { hist.ProductName, hist.Total });
L>}
L>
L>И все.
это не все, если уж быть до конца честным, давайте рассмотрим еще и классы врапперы CustOrderHistResultEntry...хорошо если процедура состоит из банального select и дизайнер сумеет таки сгенерить вам класс, хотя, как вы сами здесь и утверждаете S>Сорри, что вмешиваюсь, но получение схемы результсета хранимой процедуры — вполне выполнимая операция. Скажем, дадасет дизайне такое умеет. L>Значит ошибался. А где можно посмотреть как оно работает?
класс-врапперы вы не генерите, а пишите сами, это и есть вручную или я ошибаюсь?
Вообще, при более-менее сложной логике сигнатура возвращаемых данных может быть гораздо сложнее, это и преобразования типа, и вычисляемые поля, и вложенные select для конкретного поля из записи рекордсета...и тут уже приходится писать такие классы вручную, что собственно и приводит к необходимости написания "трекинга" кода именно вручную...
Возвращаясь (просто уж о наболевшем в конктексте использования процедур в linqtosql): L>Как видишь, никакой магии и правки руками. Только стандартный функционал.
такой же "стандартный" функционал есть классическое использование datareader|dataset, и в данном конкретном случае необходимости в линке вообще не вижу
DШ>>я понял что вы имеет ввиду, магия здесь в классах CustOrderHistResultEntry и в поддержке такиго рода в синхронном состоянии L>Опишите свой вариант. Как вы поддерживаете синхронность кроме как руками? Я вариантов вообще не вижу. Более того, у меня есть подозрение, что это нельзя сделать атоматически всилу того, что sqlserver не возвращает схему резалтсетов, следующих за первым. Хотя по этому поводу я не на 100% уверен.
да здесь я не спорю, я как раз и утверждаю, что такого рода синхронность добиться сделать ну практически нереально...точнее, можно сделать, но просто лишив программиста вообще такого слоя как структура базы данных, тем самым просто придя к понятию объектных хранилиш, где за основу берется интерфейс самого класса, а не структура таблиц и сигнатур процедур, чтото вроде db4o
Здравствуйте, Spender, Вы писали:
S>На самом деле ли LINQ к Store Procedure сможет улучшить производительность системы?
Нет это чушь.
SP могут увеличить производительность только за счет того, что можно будет множество запросов выполнить не покидая процесса сиквила. Что же касается компиляции запросов, то как раз linq тут вне конкуренции. Он порождает параметризованные запросы которые отлично компилируются и используются повторно. Более того, linq может оказаться предпочтительнее в случае сложных изменяемых многопараметрических запросов, так как он порождает конечный набор параметризованных запросов которые отлично кэшируются. Реализовать тоже самое в рамках хранимых процедур будет значительно сложнее.
Так что ваш начальник просто не владеет информацией и делает поспешные выводы. Я бы на его месте покурил бы статьи посвященные оптимизации многопараметрических запросов и произвел бы тесты.
Что касается оптимизации межпроцессного взаимодействия, то тут могут помочь хранимки написанные на дотнете (если конечно сервером выступает MS SQL). В них можно применять linq и они выполняются в рамках процесса сиквела.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, TK, Вы писали:
TK>Плюс хранимой процедуры в том, что ее можно "оптимизировать" не трогая оригинальное приложение. в остальном, современные SQL сервера умеют кешировать планы выполнения запросов.
Проблема в том, что если хранимка не прямолинейна, то очень не просто добиться для нее хороших планов для разных входных параметров. Линк же будет генерировать разные запросы которые по определению будут давать более оптимальные планы.
Что касается оптимизации, то у MS SQL 2008 в этом плане есть существенные улучшения, так что и для отдельных запросов можно добиться хороших результатов.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Spender, Вы писали:
S>[крик души]
S>Нафига все это нужно?!?! Если для того, чтобы получить 1 запись из базы вынимаются все!!! и потом из них уже возвращается одна. Либо я чего-то не понимаю. Ведь быстрее вытащить только то, что нам надо, чем потом искать?!?!
Мне кажется, вы не совсем правильно поняли, что имелось в виду.
Например, у вас есть хранимая процедура GetOrder. Она принимает сл. параметры: @OrderID, @WithOrderLines, @WithDeliveryHistory.
Соответственно, когда вы запустили ее вот так:
, то она тоже вернет два рекордсета: 1) "шапка" заказа 2) строчки истории доставки. Но в этом случае второй рекордсет будет уже другим (его колонки могут отличаться).
Как получить схему резалтсета такой процедуры лично мне совсем не понятно. Единственный вариант, который я вижу — это самостоятельно это разруливать руками.
Здравствуйте, Tom, Вы писали:
TK>>Почитайте тут: http://msdn.microsoft.com/ru-ru/library/ms181055.aspx TK>>В остальном, надо исходить из того, что SQL Server хранит только исходный код хранимых процедур и триггеров. При выполнении хранимой процедуры или триггера в первый раз исходный код компилируется в план выполнения. т.е. разница только в том, где будет хранится "текст" запросов. в случае с хранимыми процедурами (особенно если их тысячи) вы "усложняете" себе поддержку вашего решения.
Tom>А в чём усложнение?
А замена проверяемого во время компиляции, поддающегося рефакторингу и хранимого в системе контроля версий кода на код хранимый в БД, проверяемый только во время интерпретации и плохо поддающийся рефаторингу — это не усложнение?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Lloyd, Вы писали:
S>>[крик души]
L>Мне кажется, вы не совсем правильно поняли, что имелось в виду.
Все что Вы написали, я понимаю. Это же был крик души на то, что я увидел в коде системы. Для получения одной записи вытаскиваются все из БД, а потом уже полученный результат преобразуется в List<T> и там ищется по параметрам.
Здравствуйте, VladD2, Вы писали:
VD>Проблема в том, что если хранимка не прямолинейна, то очень не просто добиться для нее хороших планов для разных входных параметров. Линк же будет генерировать разные запросы которые по определению будут давать более оптимальные планы.
Если запросы отличаются только параметрами, то генерируемый sql будет одним и тем же.
Здравствуйте, Spender, Вы писали:
S>Все что Вы написали, я понимаю. Это же был крик души на то, что я увидел в коде системы. Для получения одной записи вытаскиваются все из БД, а потом уже полученный результат преобразуется в List<T> и там ищется по параметрам.
В какой системе вы это увидели и какое отношение это имеет к linq2sql?
Здравствуйте, gandjustas, Вы писали:
G>производительность системы — да, производительность программистов от этого сильно уменьшится.
Первое — не факт. Есть огромный шанс, что производительность системы тоже уменьшится.
Компиляция планов не единственный показатель влияющий на производительность сервера БД.
Учитывая, что планы в linq кэшируются по определению намного важнее смотреть на то насколько оптимальными будут эти планы. Лнин будет генерировать разные запросы для разных сочетаний условий. Это приведет к созданию более точных планов. А вот добиться того же с помощью хранимок не так просто.
Вы будете смеяться, но один из советов по оптимизации сложных хранимых процедур — это сброс кэша запросов при их выполнении. А другой — использование динамической генерации SQL-я. Эти подходы порождают оптимальные планы запросов. Если БД имеет огромный размер, лучший план запроса может оказаться лучшим выбором нежели экономия на компиляции планов выполнения.
Вот такие парадоксы бывают в наше время.
А вывод? Вывод простой. Преждевременная оптимизация (точнее оптимизация без понимания внутренних процессов) вредна. И если ты не знаешь, что будет узким местом, то лучше напиши в лоб и воспользуйся профайлером.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Lloyd, Вы писали:
L>В какой системе вы это увидели и какое отношение это имеет к linq2sql?
Я увидел это в той системе участие в разработке которой я принимаю. Изначально вопрос был "Помогут ли хранимки повысить производительность". Но как могут помочь хранимки, если код написан через ... По этому я и назвал это "Криком души". В общем плохо все. Linq2sql тут не причем.
Здравствуйте, IB, Вы писали:
IB>Править нет. А вот когда нужно понять что происходит или что-то поменять с предсказуемым результатом — процедуры рулят.
Вань, а что же они у нас то не рулят на сервере?
IT тут недавно рассказывал, что он какой-то там кусок на сервере переписал с использованием линка и скорость выросла в несколько раз.
Какое-то расхождение теории и практики.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Tom, Вы писали:
Tom>Не надо называть всех идиотами, критинами и самодурами. Это не добавляет сообщениям смысла.
Всех никто и не называл. Назвали одного самодура который дослужился до начальственных постов, а такой простой истины как — не переписывать код по одному только своему предположению — не усвоил.
То что озвучил здесь автор темы — это однозначно самодурство и полный не проффесионалим.
Можно спорить о том, что лучше строготипизированные запросы или гибкость оптимизации планов, но факт остается фактом. То ради чего их начальник хочет заставить их переписывать код — это смешно. Полная некомпетентность. Не шаришь в технологиях, не принимай решений. Сначала тестируй, потом анализируй.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Spender, Вы писали:
S>Может я телефончик его дам, Вы ему тоже это скажете. Наша команда замудохалась объяснять ему это. Нагрузочные тесты у нас выглядят так. Берутся все программисты и начинают тыкать по кнопочкам, в это время смотрится загрузка SQL сервера.
Зашибись!
Тебе о другом думать надо. Куда бы из этого отдела (или компании) срыть.
Как вариант, попробовать объяснить эти доводы начальству твоего начальства. Правда будет выглядеть как "стук".
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Spender, Вы писали:
S>Я тут ещё одно уточнение хочу вставить. S>Проблема именно в том, что SQL сервер перестает отвечать клиентам. Т.е. считается, что он очень сильно нагружается из-за того, что ему каждый раз приходится компилить запросы.
Это бред!
А слабо открыть SQL Profiler и поглядеть в чем собственно дело?
Сделайте нормальные нагрузочные тесты.
Выявите запросы которые кладут сервер.
Тогда и будет ясно, что делать чтобы исправить проблему.
Если уж пытаться угадать, то надо вспомнить, что сервер сокрее можно положить одним-двумя ужасно оптимизированными запросам нежели компиляцией запросов.
Вы же не MS SQL 6.5 используете? Это в нем компилировались планы только для запросов из хранимок, а компиляция запроса содержащего 5 и более соединений могла продолжаться минутами. Сейчас же все в точности на оборот.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Spender, Вы писали:
S>Если бы я все это умел У нас есть человек специальный для этого. Он полностью занимается БД на стороне SQL сервера. Может даже оптимизирует что-то там. Но вряд ли.
Ё моё! Ты думаешь, что тут все родились с SQL Profiler-ом в анусе и знанием SQL в мозге?
Прочти пару-тройку статей по выявлению проблем производительности в SQL Server. Потрахайся сам пару-тройку дней и все поймешь. С отладчиком ведь справляешься? Ну, так это не сильно сложнее.
S>Спасибо за совет. Попробую все это рассказать шефу.
Тебе Spender мудрую мысль сказал. Послушай его. Найди проблему сам и без выпендрежа и пыжения, аккуратно продемонстрируй ее решение начальнику. Тогда ты и проблему решишь, и уважение начальника заслужишь. Еще один бонус — получишь новые знания которые лишними никогда не бывают.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: LINQ vs Store Procedure
От:
Аноним
Дата:
20.03.09 22:22
Оценка:
Здравствуйте, VladD2, Вы писали:
VD>А замена проверяемого во время компиляции, поддающегося рефакторингу и хранимого в системе контроля версий кода на код хранимый в БД, проверяемый только во время интерпретации и плохо поддающийся рефаторингу — это не усложнение?
Сам я сторонник Linq, но тут вы отстали от жизни.
В Visual Studio есть тип проекта для базы данных SQL Server.
Поддерживается контроль версий, проверка во время компиляции и в какой-то мере рефакторинг.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, gandjustas, Вы писали:
G>>производительность системы — да, производительность программистов от этого сильно уменьшится.
VD>Первое — не факт. Есть огромный шанс, что производительность системы тоже уменьшится.
От тупого переноса всего в ХП вряд ли. Запросы теже самые, параметры тоже.
VD>Компиляция планов не единственный показатель влияющий на производительность сервера БД. VD>Учитывая, что планы в linq кэшируются по определению намного важнее смотреть на то насколько оптимальными будут эти планы. Лнин будет генерировать разные запросы для разных сочетаний условий. Это приведет к созданию более точных планов. А вот добиться того же с помощью хранимок не так просто.
Насчет Linq2SQL не уверен, а за EF замечал что он незначащие части запроса выкидывать умеет (хотя оптимизатор сиквеля также их выкинет).
AFAIK оптимизировать запросы на клиенте — гиблое дело, слишком мало информации и уж очень декларативен SQL.
VD>Вы будете смеяться, но один из советов по оптимизации сложных хранимых процедур — это сброс кэша запросов при их выполнении. А другой — использование динамической генерации SQL-я. Эти подходы порождают оптимальные планы запросов. Если БД имеет огромный размер, лучший план запроса может оказаться лучшим выбором нежели экономия на компиляции планов выполнения.
Это если условия фильтрации могут зависить от параметров. Но при тупом переносе запросов в ХП такого не возникнет.
VD>А вывод? Вывод простой. Преждевременная оптимизация (точнее оптимизация без понимания внутренних процессов) вредна. И если ты не знаешь, что будет узким местом, то лучше напиши в лоб и воспользуйся профайлером.
+1
У меня по поводу Linq to SQL \ EF обладают офигенным преимуществом. Они в коде программы позволяют строить проекции и накладывать дополнительные фильтры, что может увеличить производительность в разы.
ХП этому мешают. В принципе можно делать ХП для каждой выборки, но так мало кто поступает, обычно делают 4 crud процедуры и на этом успокаиваются.
Здравствуйте, VladD2, Вы писали:
VD>Ё моё! Ты думаешь, что тут все родились с SQL Profiler-ом в анусе и знанием SQL в мозге? VD>Прочти пару-тройку статей по выявлению проблем производительности в SQL Server. Потрахайся сам пару-тройку дней и все поймешь. С отладчиком ведь справляешься? Ну, так это не сильно сложнее.
Конечно не родились. Но у меня своей работы до одного места. Я в эту компанию пришел месяц назад. Также по мимо меня взяли ещё и спеца по БД, с которым я сегодня поговорил и он тоже против тупого перехода на хранимки. Но к БД нас никто не пустит. Там своих людей хватает. Так что мы можем только идеи дать
Здравствуйте, VladD2, Вы писали:
VD>Тебе о другом думать надо. Куда бы из этого отдела (или компании) срыть. VD>Как вариант, попробовать объяснить эти доводы начальству твоего начальства. Правда будет выглядеть как "стук".
Начальник у нас один, он же шеф, он же директор. Срыть я не могу, так как в Канаде без Канадского опыта тяжко. Я свою работу делаю. Хотел просто помочь. Спасибо за советы. Учту.
Здравствуйте, Sinix, Вы писали:
S>По сабжу. Ado.NET Team продолжает традиции МС в разработке фреймворков для доступа к данным: вместо того, чтобы довести хоть одну технологию до ума, они вечно бросаются из крайности в крайность — то у нас рулит disconnected approach и датасеты, то нифига, бизнесь не выживет без ормапперов с поддержкой наследования и статически верифицируемых запросов к СУБД.
И где здесь "из крайности в крайность"? Датасеты не имеют никакого отношения к ORM и ни датасеты ни ORM никак не связаны с "disconnected approach".
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, Lloyd, Вы писали:
Tom>>О, а можно пару слов, про процедуру внесения изменений в схему? L>Да я тут ничего особо умного не скажу, просто здравый смысл: изменения, вносимые одним разработчиком, не должны мешать работать другому. L>Поэтому желательно чтобы у каждого разработчика была своя база и разработка велась на ней. При выкладывании в сорс-контрол должны одноврененно выкладываться скрипты для базы и изменения в сущностях.
Я так понял, что эта система "не дуракоустойчивая"? То есть есть возможность "забыть" "одновременно выложить" и поломать на какое-то время хранилище?
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, VladD2, Вы писали:
Tom>>Не надо называть всех идиотами, критинами и самодурами. Это не добавляет сообщениям смысла.
VD>Всех никто и не называл. Назвали одного самодура который дослужился до начальственных постов, а такой простой истины как — не переписывать код по одному только своему предположению — не усвоил.
VD>То что озвучил здесь автор темы — это однозначно самодурство и полный не проффесионалим.
Вообще-то неизвестно, может начальник на самом деле посиделв проайлере, что-то там себе надумал и просто не всё всем рассказал. Да и вообще судить о ком-то с треьих слов дело неблагодарное
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, Lloyd, Вы писали:
L>Здравствуйте, DuШes, Вы писали:
L>Пожалуйста, если пишешь ответ, пиши его в ту ветку, к которой он относится. Невозможно же читать.
бросаю свои попытки вести с вами дискуссию, вы давно уже перешли на личности и умеете слушать только себя
Здравствуйте, _FRED_, Вы писали:
L>>Да я тут ничего особо умного не скажу, просто здравый смысл: изменения, вносимые одним разработчиком, не должны мешать работать другому. L>>Поэтому желательно чтобы у каждого разработчика была своя база и разработка велась на ней. При выкладывании в сорс-контрол должны одноврененно выкладываться скрипты для базы и изменения в сущностях.
_FR>Я так понял, что эта система "не дуракоустойчивая"? То есть есть возможность "забыть" "одновременно выложить" и поломать на какое-то время хранилище?
Здравствуйте, DuШes, Вы писали:
L>>Пожалуйста, если пишешь ответ, пиши его в ту ветку, к которой он относится. Невозможно же читать.
DШ>бросаю свои попытки вести с вами дискуссию, вы давно уже перешли на личности и умеете слушать только себя
Офигеть просто. Не отвечал ни на один вопрос, обвинял меня не пойми в чем, перемешивал ветки по своему усмотрению, а в итоге оказывается я перешел на личности и умею слушать только себя. Супер!
Здравствуйте, _FRED_, Вы писали:
_FR>Я так понял, что эта система "не дуракоустойчивая"? То есть есть возможность "забыть" "одновременно выложить" и поломать на какое-то время хранилище?
Здравствуйте, Spender, Вы писали:
VD>>Ё моё! Ты думаешь, что тут все родились с SQL Profiler-ом в анусе и знанием SQL в мозге? VD>>Прочти пару-тройку статей по выявлению проблем производительности в SQL Server. Потрахайся сам пару-тройку дней и все поймешь. С отладчиком ведь справляешься? Ну, так это не сильно сложнее.
S>Конечно не родились. Но у меня своей работы до одного места.
У всех работы выше крыше. Просто один повышает свой уровень и производительность труда, а другой ищет отмазки почему он это не может сделать. На форум же у тебя время нашлось?
Потрать, в конце концов, свое личное время. Останься пару раз после работы... Найди узкое место и реши проблему.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, gandjustas, Вы писали:
VD>>Первое — не факт. Есть огромный шанс, что производительность системы тоже уменьшится. G>От тупого переноса всего в ХП вряд ли. Запросы теже самые, параметры тоже.
Запросы будут другие. Linq позволяет строить запросы по частям. Скажем создал базовую часть, а потом добавил к ней фильтрацию. В другом случае добавил другую фильтрацию. При этом будут порождены разные запросы каждый из которых получит оптимальный план и будет закэширован.
Перенести этот подход в хранимки просто так не выйдет. Придется или клепать динамический, параметризованный SQL, что даст примерно ту же производительность, но при этом резко усложнит реализацию. Если же начать использовать разные выверты вроде добавление параметров через OR (с расчетом на то, что не заданные выражения не будут учтены), то план запросов в некоторых случаях может стать очень плохим. Единственное что можно будет сделать — это явно выключить кэширование. А это сразу же приведет к постоянной перекомпиляции запросов. Результат — снижение производительности.
VD>>Компиляция планов не единственный показатель влияющий на производительность сервера БД. VD>>Учитывая, что планы в linq кэшируются по определению намного важнее смотреть на то насколько оптимальными будут эти планы. Лнин будет генерировать разные запросы для разных сочетаний условий. Это приведет к созданию более точных планов. А вот добиться того же с помощью хранимок не так просто. G>Насчет Linq2SQL не уверен, а за EF замечал что он незначащие части запроса выкидывать умеет (хотя оптимизатор сиквеля также их выкинет). G>AFAIK оптимизировать запросы на клиенте — гиблое дело, слишком мало информации и уж очень декларативен SQL.
Я говорил совершенно о другом. Читай внимательнее.
Почти тоже самое я повторил выше.
VD>>Вы будете смеяться, но один из советов по оптимизации сложных хранимых процедур — это сброс кэша запросов при их выполнении. А другой — использование динамической генерации SQL-я. Эти подходы порождают оптимальные планы запросов. Если БД имеет огромный размер, лучший план запроса может оказаться лучшим выбором нежели экономия на компиляции планов выполнения. G>Это если условия фильтрации могут зависить от параметров.
Если приложение не примитивно, то так оно и будет.
G>Но при тупом переносе запросов в ХП такого не возникнет.
А как ты себе видишь тупой перенос логики динамически собираемого linq-запроса?
Всю логику которую за нас выполняет linq прийдется повторить в хранимках. А это не тривильная задача. Более того — это задача требующая высокой квалификации того кто будет писать хранимки. В итоге как раз может оказаться так, что люди восползуются самыми простыми средствами воде "not x is null or x > 1", что в итоге приведет к дикому падению производительности в следствии выбора плохих планов.
G>У меня по поводу Linq to SQL \ EF обладают офигенным преимуществом. Они в коде программы позволяют строить проекции и накладывать дополнительные фильтры, что может увеличить производительность в разы.
О том и речь.
G>ХП этому мешают.
Они этому не мешают. Они резко усложняют этот процесс. Создать аналогичную хранимку можно. Но она будет намного сложнее аналогичного linq-запроса, так как вынуждена будет содержать не тривильный динамический SQL, отлаживать который очень не просто.
G>В принципе можно делать ХП для каждой выборки, но так мало кто поступает, обычно делают 4 crud процедуры и на этом успокаиваются.
Мне кажется совершенно не реально делать хранимки на все сочетания запросов. Сочетания запросов вызовут комбинаторный взрыв, что сделает невозможным написание кода хранимок вручную. Конечно можно создать некую мета-программу которая сгенерирует код таких хранимок, но это само по себе сложная работа. Да и вся БД будет забита кучей хранимок многие из которых будут вызваться раз в сто лет, а некоторые вообще не будут вызваться.
Тут опять же есть решеие — генерировать хранимки по требованию (в ленивом режиме). Но это еще больше усложнит задачи. А толку — 0.
Так что я бы на месте этой конторы поступил бы так:
1. Выяви бы причину тормозов и устранил бы ее. Это точно не linq.
2. Если проблема в некоторых тяжелых запросах, то их (и только их) я бы вынес в хранимки или оптимизировал бы каким-то другим образом (например, с помощью создания материализованных представлений).
3. Встроил бы в программу подсистему мониторинга производительности которая автоматически выявляла бы узкие места и информировала бы о них админов и разработчиков.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Lloyd, Вы писали:
VD>>Проблема в том, что если хранимка не прямолинейна, то очень не просто добиться для нее хороших планов для разных входных параметров. Линк же будет генерировать разные запросы которые по определению будут давать более оптимальные планы.
L>Если запросы отличаются только параметрами, то генерируемый sql будет одним и тем же.
Читай внимательно выделенное. То что план будет одним и тем же для запроса выбирающего миллион записей и оду — это очень плохо.
Грамотные люди для оптимизации сложных нелинейных хранимок используют в них генерацию и динаическое исполнение параметризованного SQL-я. Тогда планы кэшируются для разных запросов и их оптимальность становится выше.
Более того. Иногда имеет смысл отказаться от кэширования планов (когда разные значения имеют разную релевантность).
В общем, это отнюдь не простой вопрос.
Линк же во многом решает эти проблемы так как генерирует специализированный, но при этом параметризованный SQL. Так что переход на хранимки может вызвать проблемы с производительностью (при упрощенной реализации) и привести к усложнению реализации.
Остается вопрос. Зачем это делать?
Если переходить на хранимки, то нужно менять стратегию обработки данных. Это уже не тупой перенос кода на сервер.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
VD>А замена проверяемого во время компиляции, поддающегося рефакторингу и хранимого в системе контроля версий кода на код хранимый в БД, проверяемый только во время интерпретации и плохо поддающийся рефаторингу — это не усложнение?
А почему он не поддаётся рефакторингу? Для этого есть соотвестствующая студия — Database Edition GDR. Ну если она не устраивает — есть как обычно внещние средства.
Здравствуйте, VladD2, Вы писали:
VD>А как ты себе видишь тупой перенос логики динамически собираемого linq-запроса? VD>Всю логику которую за нас выполняет linq прийдется повторить в хранимках. А это не тривильная задача. Более того — это задача требующая высокой квалификации того кто будет писать хранимки. В итоге как раз может оказаться так, что люди восползуются самыми простыми средствами воде "not x is null or x > 1", что в итоге приведет к дикому падению производительности в следствии выбора плохих планов.
Я один раз участвоввал в процессе переноса динамически генерируемого SQL в программе.
Саначала тупо делали по 4 продецуры. Когда выяснилось что генерация SQL-кода на сервере и исполнение через execsql работает медленее, то разделили хранимки на несколько, код каждой был статическим, а из программы вызывали нужную в зависимости от сочетания условий.
Потом я эти проектом больше не занимался, но все говорят что быстрее работать стало. Замеров видимо никто не проводил.
Здравствуйте, VladD2, Вы писали:
L>>Если запросы отличаются только параметрами, то генерируемый sql будет одним и тем же.
VD>Читай внимательно выделенное. То что план будет одним и тем же для запроса выбирающего миллион записей и оду — это очень плохо.
Формулировка была не очень удачная. Тут скорее следовало говорить не о "линк .. будет генерировать разные запросы", а что "с помощью линка проще сгенерировать разные запросы". Иначе у чающего может возникнуть впечатление, что линк что-то сам в состоянии сделать.
По порядку.
1) disconnected как бы подразумевает, что мы могём нормально работать с датасорс без соединения к серверу. В случае ef нам приходится писать кэш/modelView ручками. Почитайте беседу с Бен-Ами (товарищ осуществляет поддержку по EF и общается с обществом, эдакий полуофициальный голос ado.net team. Про роль внутри команды не в курсе): (http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/172ae667-d20a-4dbf-9e98-39b90387b4f4/).
Он там говорит, что контекст у них рассматривается как unit of work. Отсюда все грабли. В частности то, что они не собираются делать сериализуемый контекст/change tracking. А проблемы все из-за не совсем разумного решения отделить хранение изменений объекта от него самого. Религия poco, что поделаешь В результате, у нас либо идеологически чистые объекты, которые легко передаются через, скажем, wcf, либо грабли с чанж-трекингом который надо реализовывать целиком и полностью самостоятельно.
Вот и выходит, что без самописного велосипеда ef тяжко применять для передачи сущностей между аппсервером /клиентом (хотя это может и в плюс), так и на тяжёлом клиенте.
2) не-не, вы правы что получить схему можно только по первому резалтсету. По большому секрету, есть и ещё более страшные ограничения — если ХП обращается, например к временным таблицам — схему получить низзя. Впрочим страдать от этого имхо глупо. Детально этой байдой не занимался, рассказать как оно работает не смогу.
Здравствуйте, _FRED_!
_FR>И где здесь "из крайности в крайность"? Датасеты не имеют никакого отношения к ORM и ни датасеты ни ORM никак не связаны с "disconnected approach".
Вот если бы они развивали параллельно датасеты и орм и шли бы на сближение/плавную замену — всё было бы в порядке. Дык нет, EF у товарищей — новая унифицированная платформа, и на ней будет жить как минимум oslo, azure, ssds (если оно наконец доживёт до релиза) и acropolis (если его вытащат из инкубатора — слухи ходют ).
Датасеты как раз имеют отношение к disconnected approach, точнее к тому, что понималось под partially disconnected applications когда писался первый ado.net. Они собсно и предназначались в первую очередь изображать из себя локальный кэш (и неплохо таки с этим справляются), а сериализация/передача между tiers — это так, рюшечки.
ef, соответственно, задумывался слегка для других вещей, и проблемы, решающиеся элементарно для датасетов (хранение согласованного снимка данных, валидация, биндинг, отсоединённый режим, одновременная работа с любыми провайдерами) там решаются тяжелее или не решаются вообще. Ссылка на обсуждение — в моём ответе Ллойду. В одном из последних постов по ссылке — ссылка на баг у DataView (ListChanged генерится только для первого из созданных к одной таблице DataView).
Здравствуйте, Sinix, Вы писали:
_FR>>И где здесь "из крайности в крайность"? Датасеты не имеют никакого отношения к ORM и ни датасеты ни ORM никак не связаны с "disconnected approach".
S>Вот если бы они развивали параллельно датасеты и орм и шли бы на сближение/плавную замену — всё было бы в порядке. Дык нет, EF у товарищей — новая унифицированная платформа, и на ней будет жить как минимум oslo, azure, ssds (если оно наконец доживёт до релиза) и acropolis (если его вытащат из инкубатора — слухи ходют ).
Все здравомыслящие люди довольно быстро осознали, что с датасетами связываться не стоит Аргументом этому факту является то, что запоследние лет пять на тему того, как здорово пользоваться датасетами не видно ни одной статьи от признаного в своём деле специалиста. Даже наоборот, при желании можно отыскать стотью о торм, почему датасетами пользоваться не нужно…
S>Они вон пять лет ленятся добавить поддержку nullable values в дизайнер датасетов — http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataset/thread/2e1c4146-994a-4ebb-b090-fd271aebb880/ (это самый свежий топик). Чтобы добиться от них признания бага в датасете мне пришлось охотицца за саппортом 7 месяцев (на принцип пошёл ). Так что не стоит надеяться на то, что датасеты и дальше будут жить и развиваться.
…поэтому рассуждения о том, что надо было бы добавить в них звучат довольно странно. Поленились в своё время написать нормальный слой работы с данными, бизнес-логики и представления — мучайтесь с датасетами.
S>Датасеты как раз имеют отношение к disconnected approach, … S>ef, соответственно, задумывался слегка для других вещей, …
Я совсем не знаком с EF, но неужели что-то мешает использовать её в отсоединёной моделе? Я не спорю о том, что для чего предназначалось, но не наблюдаю непоследовательности.
Help will always be given at Hogwarts to those who ask for it.
[....] VD>А замена проверяемого во время компиляции, поддающегося рефакторингу и хранимого в системе контроля версий кода на код хранимый в БД, проверяемый только во время интерпретации и плохо поддающийся рефаторингу — это не усложнение?
проверка на этапе компиляции огромный плюс тут спорить не о чем...но никто же не мешает проверять типы, структуру, отвалилдировать схему xml входимых получаемых данных со стороны процедуры.
во-вторых, нельзя рассматривать процедуру как обычный sql-запрос, процедуры не обязательно выполняют роль для простых ABCD операций только над data-объектами, это и получение репортов, и аудит изменений, да множество на самом деле сценариев вплоть до обслуживания той же базы, с очень сложной логикой, с курсорами, с динамическими скриптами, с получением динамических рекордсетов, когда действительно структура возвращаемого результата зависит от входящих данных, и тут уже ну практически не возможно описать логику средствами linq... нет, можно, но просто усилия будут несопоставимы, то что делается естественным образом средствами t-slq (или средствами любого другого диалекта sql, не обязательно sql server) сейчас по крайней мере очень тяжело вписывается в linq, возможно в будущем ситуация изменится
Здравствуйте, gandjustas, Вы писали:
G>Я один раз участвоввал в процессе переноса динамически генерируемого SQL в программе. G>Саначала тупо делали по 4 продецуры. Когда выяснилось что генерация SQL-кода на сервере и исполнение через execsql работает медленее, то разделили хранимки на несколько, код каждой был статическим, а из программы вызывали нужную в зависимости от сочетания условий. G>Потом я эти проектом больше не занимался, но все говорят что быстрее работать стало. Замеров видимо никто не проводил.
Когда 4 это нормально, но при увеличении инвариантов запроса мы получаем комбинаторный взрыв либо возврат к execsql.
Здравствуйте, Sinix, Вы писали:
S>По порядку. S>1) disconnected как бы подразумевает, что мы могём нормально работать с датасорс без соединения к серверу. В случае ef нам приходится писать кэш/modelView ручками. Почитайте беседу с Бен-Ами (товарищ осуществляет поддержку по EF и общается с обществом, эдакий полуофициальный голос ado.net team. Про роль внутри команды не в курсе): (http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/172ae667-d20a-4dbf-9e98-39b90387b4f4/).
На самом деле ничего ручками писать не надо. Все уже написано до нас.
S>Он там говорит, что контекст у них рассматривается как unit of work. Отсюда все грабли. В частности то, что они не собираются делать сериализуемый контекст/change tracking. А проблемы все из-за не совсем разумного решения отделить хранение изменений объекта от него самого. Религия poco, что поделаешь В результате, у нас либо идеологически чистые объекты, которые легко передаются через, скажем, wcf, либо грабли с чанж-трекингом который надо реализовывать целиком и полностью самостоятельно.
Какой-то неправльный вывод. Проблемы как раз из-за недостаточного отделения change-tracking от контекста.
S>Вот и выходит, что без самописного велосипеда ef тяжко применять для передачи сущностей между аппсервером /клиентом (хотя это может и в плюс), так и на тяжёлом клиенте.
ADO.NET Data Services, Entity Bag и Sync Services решают если не все, то подавляющее большентсво проблем.
Дня вам!
_FR>Все здравомыслящие люди довольно быстро осознали, что с датасетами связываться не стоит Аргументом этому факту является то, что запоследние лет пять на тему того, как здорово пользоваться датасетами не видно ни одной статьи от признаного в своём деле специалиста. Даже наоборот, при желании можно отыскать стотью о торм, почему датасетами пользоваться не нужно…
_FR>... Поленились в своё время написать нормальный слой работы с данными, бизнес-логики и представления — мучайтесь с датасетами.
Скажем так, у нас наверно специфика такая, но тем не менее — датасеты вполне себе успешно используются и работают.
Основное применение — локальный кэш/модель данных для десктоп клиента.
Что делает:
1) кэш/согласованный набор данных. Структура обычно нетривиальная, с кучей зависимостей, поэтому проще и выгодней залить набор сразу, чем постоянно дёргать сервер и разруливать грабли с несогласованной информацией
2) локальная валидация изменений. Вам ведь не надо рассказывать чем это хорошо?
3) стандартные интерфейсы для биндинга. Возможность биндинга с разными фильтрами к одним и тем же элементам. Тоже must have.
4) индексы и быстрый поиск. локальная фильтрация/сортировка.
5) out-of-context change-trackiing.
6) Однотипная работа с добавленными/изменёнными/далёнными данными.
7) Изоляция от провайдера/возможность одновременно использовать произвольных провайдеров.
всё это нам реально надо (ну разве что 7 не совсем критично).
Повторюсь — это клиент. Сервера в чистом виде в большинстве случаев нет — доступ идёт к СУБД через прослойку из хранимых процедур/представлений (тоже специфика.
При таком раскладе как-то неудобно говорить, что датасеты отстой или что-то ещё рулит для дескоп-клиента.
Переписывать смысла нет — во-первых мы потеряем кучу времени, во-вторых функционал будет процентов на 90 повторять функционал датасетов. То что нам надо + некоторые мелкие косяки (типа неподдержки nullable) вполне кошерно решаются кастомным шаблоном T4.
Если вы знаете что-то дотнетовское, что удовлетворяет требованиям 1-6 — с радостью посмотрю и ознакомлюсь. EF сюда не подходит.
_FR>Я совсем не знаком с EF, но неужели что-то мешает использовать её в отсоединёной моделе? Я не спорю о том, что для чего предназначалось, но не наблюдаю непоследовательности.
Вам придётся во-первых сделать eager load для всех возможных путей обращения к элементам + убедиться, что контекст разрезолвил дубликаты, полученные по разным связям. Если вы используете ХП, вам приходится добавлять все сущности в контекст ручками (там ещё пара тонокстей — сейчас не вспомню) и заполнять EntitySet/EntityReference у связаннных сущностей. Дальше есть нюансы с удержанием сущности в контексте/его очистке после апдейта и перед заливкой новых данных.
Даже если вы победите эти ограничения — в чистом виде entities не биндятся — см в ссылке на мсдн-ский форум. Дальше вы не можете сделать проверки на изменение элементов в контексте. Плюс хитрые подвыверты на получение original-значений изменённых данных... Это только то, с чем я пытался бороться. Про сложный биндинг с динамической фильтрацией /many-to-many/сложные зависимости молчу.
Здравствуйте, Sinix, Вы писали:
S>Если вы знаете что-то дотнетовское, что удовлетворяет требованиям 1-6 — с радостью посмотрю и ознакомлюсь. EF сюда не подходит.
Очень подходит локальная БД SqlCE + Sync Services + тот же EF для работы с данным из кода.
Здравствуйте, gandjustas.
G>На самом деле ничего ручками писать не надо. Все уже написано до нас.
С этого момента поподробнее. По ссылке что я привёл:
...I do not like binding UIs directly to entities as that often results in code pollution over time. My preference is typically to create a view model for my entities and bind the UI to them instead — that allows me to provide validation and error checking, more robust change notification, can make binding through object graphs much easier, and allows me to format/lazy load/expose properties that may perform some UI-specific transformation...
Либо товарищ чего-то не знает, либо я не смог добиться от него нужного ответа. По его мнению без самописного view model проверок/оповещений об изменениях не будет.
G>Какой-то неправльный вывод. Проблемы как раз из-за недостаточного отделения change-tracking от контекста.
Сорри если невнятно написал. В EF чанж-трекинг живёт в контексте, entity — практически POCO и изменений внутри себя не хранит. В результате в плюсах — лёгкая сериализация entities как они есть, в минусах — отсутствие стандартного механизма сериализации изменений. Так что да, проблемы как раз из-за недостаточного отделения change-tracking от контекста.
G>ADO.NET Data Services, Entity Bag и Sync Services решают если не все, то подавляющее большентсво проблем.
Сейчас мы вроде беседуем о EF как DAL для десктоп-клиента, нет? Заводить middleware и переводить всё на rest только из-за особенностей клиентского фреймворка неразумно получится. Sync Services во-первых не работают напрямую с EF — у нас получается ef + sql compact + sync services. Во-вторых они накладывают определённые ограничения на схемы данных и требуют прямого доступа к таблицам — не для всех клиентов такое подходит.
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, gandjustas.
G>>На самом деле ничего ручками писать не надо. Все уже написано до нас.
S>С этого момента поподробнее. По ссылке что я привёл: S>
S>...I do not like binding UIs directly to entities as that often results in code pollution over time. My preference is typically to create a view model for my entities and bind the UI to them instead — that allows me to provide validation and error checking, more robust change notification, can make binding through object graphs much easier, and allows me to format/lazy load/expose properties that may perform some UI-specific transformation...
S>Либо товарищ чего-то не знает, либо я не смог добиться от него нужного ответа. По его мнению без самописного view model проверок/оповещений об изменениях не будет.
Смотрю сгенерированные EF классы — оповещения будут.
Для работы с графами объектов в UI я бы тоже рекомендовал viewmodel создавать.
G>>ADO.NET Data Services, Entity Bag и Sync Services решают если не все, то подавляющее большентсво проблем.
S>Сейчас мы вроде беседуем о EF как DAL для десктоп-клиента, нет? Заводить middleware и переводить всё на rest только из-за особенностей клиентского фреймворка неразумно получится. Sync Services во-первых не работают напрямую с EF — у нас получается ef + sql compact + sync services. Во-вторых они накладывают определённые ограничения на схемы данных и требуют прямого доступа к таблицам — не для всех клиентов такое подходит.
Ну если рассматривать только десктоп-клиент с непосредственным доступом в базу, то вооще зачем нужен disconnected режим?
Если многозвенное приложение, то рецепт я привел выше.
S>В общем как-то отдаёт костылями, не согласны?
Многие решения по работе с данными отдают костылями.
Здравствуйте, _FRED_, Вы писали:
_FR>Все здравомыслящие люди довольно быстро осознали, что с датасетами связываться не стоит
На мой взгляд датасэты — это хорошая идея опошленная плохой реализацией.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[28]: LINQ vs Store Procedure
От:
Аноним
Дата:
23.03.09 10:38
Оценка:
Здравствуйте, Sinix, Вы писали:
_FR>> То что нам надо + некоторые мелкие косяки (типа неподдержки nullable) вполне кошерно решаются кастомным шаблоном T4.
Не могли бы Вы привести ссылку на то как это можно реализовать.
Здравствуйте, DuШes, Вы писали:
DШ>Здравствуйте, VladD2, Вы писали:
DШ>[....] VD>>А замена проверяемого во время компиляции, поддающегося рефакторингу и хранимого в системе контроля версий кода на код хранимый в БД, проверяемый только во время интерпретации и плохо поддающийся рефаторингу — это не усложнение?
DШ>проверка на этапе компиляции огромный плюс тут спорить не о чем...но никто же не мешает проверять типы, структуру, отвалилдировать схему xml входимых получаемых данных со стороны процедуры.
Офтопик: Мне кажется более точно будет говорить не "отвалилдировать", а "вывалидировать". Это более точно отражает суть процесса .
Если серьезно, то мешает как всегда отсутствие времени и вражденное отвращение ко всем лишним и не нужным действиям.
В любом случае это будет только небольшой дополнительный контроль. Сами хранимки ведь от этого не станут надежнее. Их будет так же трудно писать как и раньше.
В общем, с точки зрения удобства разработки и качества кода подход с linq на мой взгляд предпочтительнее.
DШ>во-вторых, нельзя рассматривать процедуру как обычный sql-запрос, процедуры не обязательно выполняют роль для простых ABCD операций только над data-объектами, это и получение репортов, и аудит изменений, да множество на самом деле сценариев вплоть до обслуживания той же базы, с очень сложной логикой...
Вот именно и негоже писать такой сложный код на совершенно уродском языке вроде T-SQL или PL-SQL.
Но опять же это попытка подменить тему обсуждения. Речь шла о переносе linq-запросов в хранимки с целью устранения компиляции. Не надо забывать об этом.
DШ>с курсорами, с динамическими скриптами,
Вот, вот. С курсорами. Более дебельной реализации я и придумать не могу. Императивная обработка на уродском скриптовом языке, да еще и с ручным контролем ресурсов. Хуже только С++. Но С++ хоть скорость дает. А T-SQL кроме багов что дает?
DШ>с получением динамических рекордсетов,
Ага. Только почему бы не получать их с помощь тех самых linq-запросов? Ведь динамические запросы в T-SQL — это очень не удобно и убого.
DШ>когда действительно структура возвращаемого результата зависит от входящих данных,
Ага, ага. Но если речь о динамических запросах, то причем тут экономия на компиляции планов? Или хочется дикого замедления работы БД в будущем спровоцированного выбором плохого плана?
DШ>и тут уже ну практически не возможно описать логику средствами linq...
Ты уверен, что подумал прежде чем это сказал?
Заявление мягко говоря ламерское.
DШ> нет, можно, но просто усилия будут несопоставимы,
А, ну, то есть ты и сам понимаешь, что фигню спорол?
Тогда поясни, что же за страшные усиля вдруг появляются?
Не уж то наличие полноценных коллекций, компилируемого языка, отладчика, IDE, проверки во время компиляции — это не преимущества, а недостатки?
DШ>то что делается естественным образом средствами t-slq (или средствами любого другого диалекта sql, не обязательно sql server) сейчас по крайней мере очень тяжело вписывается в linq, возможно в будущем ситуация изменится
T-SQL — это уродский язык рожденный по недомыслию. Все что в нем есть хорошего — это SQL. Остальное — это совершенно дебильные дизайнерские решения 70-ых годов плохо замешанные в недоязык. В языке даже нет списков или массивов! Что еще можно о нем сказать? Ну, разве что в нем нужно явно уничтожать те самые курсоры.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Аноним, Вы писали:
А>Сам я сторонник Linq, но тут вы отстали от жизни. А>В Visual Studio есть тип проекта для базы данных SQL Server.
Я этим убожеством пользоваться так и не смог. Слишком много неудобств.
А>Поддерживается контроль версий, проверка во время компиляции и в какой-то мере рефакторинг.
Какой компиляции? Вот с linq-ом я набираю запрос и вижу список ошибок.
А что происходит при изменении TSQL-кода?
А что на счет динамического SQL который в TSQL не редко появляется и почти не нужен в случае linq.
Что до контроля версий, то лично я предпочитаю SVN. Как это чудо с ним скрестить?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Tom, Вы писали:
VD>>А замена проверяемого во время компиляции, поддающегося рефакторингу и хранимого в системе контроля версий кода на код хранимый в БД, проверяемый только во время интерпретации и плохо поддающийся рефаторингу — это не усложнение?
Tom>А почему он не поддаётся рефакторингу?
Tom>Автоматическому рефакторингу.
Tom>Для этого есть соотвестствующая студия — Database Edition GDR. Ну если она не устраивает — есть как обычно внещние средства.
Что это чудо умеет и где его брать?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Lloyd, Вы писали:
L>Формулировка была не очень удачная. Тут скорее следовало говорить не о "линк .. будет генерировать разные запросы", а что "с помощью линка проще сгенерировать разные запросы". Иначе у чающего может возникнуть впечатление, что линк что-то сам в состоянии сделать.
Формулировка была нормальная. Просто у тебя настоящий талант понимать все так как автор даже планировать не могу. Ну, да я кажется уже привык.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Tom, Вы писали:
VD>>>А замена проверяемого во время компиляции, поддающегося рефакторингу и хранимого в системе контроля версий кода на код хранимый в БД, проверяемый только во время интерпретации и плохо поддающийся рефаторингу — это не усложнение?
Tom>>А почему он не поддаётся рефакторингу?
Tom>>Автоматическому рефакторингу.
Tom>>Для этого есть соотвестствующая студия — Database Edition GDR. Ну если она не устраивает — есть как обычно внещние средства.
VD>Что это чудо умеет и где его брать?
Ответы на все вопросы лежат не далее трех ссылок в гугле по соответвующему запросы.
Не стоит так скептически отностится к Database Edition GDR, он реально крут, но для написания логики в SQL ничего не дает
Здравствуйте, gandjustas, Вы писали:
G>Я один раз участвоввал в процессе переноса динамически генерируемого SQL в программе. G>Саначала тупо делали по 4 продецуры. Когда выяснилось что генерация SQL-кода на сервере и исполнение через execsql работает медленее, то разделили хранимки на несколько, код каждой был статическим, а из программы вызывали нужную в зависимости от сочетания условий. G>Потом я эти проектом больше не занимался, но все говорят что быстрее работать стало. Замеров видимо никто не проводил.
Вы просто не умеете готовить динамические запросы. Нужно просто понимать одну простую вещь. MS SQL кэширует планы к запросам очень тупо. Если описывать это упрощенно, то у него есть одна хэш-таблица ключом которой является текст запроса (так как он был передан на сервер), а значением — план.
Так вот генерируя динамически запросы от вас требуется делать так, чтобы они были одинаковыми. Для этого нужно использовать параметризованные запросы. А это, в свою очередь, ставит крест на использовании EXEC для их выполнения и заставляет выполнять запросы через sp_execute.
В общем, если интересен вопрос, гуглем не сложно найти статьи серозных людей разжевывающие этот вопрос.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, gandjustas, Вы писали:
G>Ответы на все вопросы лежат не далее трех ссылок в гугле по соответвующему запросы.
G>Не стоит так скептически отностится к Database Edition GDR, он реально крут, но для написания логики в SQL ничего не дает
Первый абзац противоречит второму.
Мы ведь говорим о написании, тестировании и сопровождении кода, не так ли?
А раз так, то комплексное решение будет по любому лучше чем лотание дыр по мелочи.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
_FR>>Все здравомыслящие люди довольно быстро осознали, что с датасетами связываться не стоит VD>На мой взгляд датасэты — это хорошая идея опошленная плохой реализацией.
Какая именно идея в них хороша и что в реализации подкачало?
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>>>Все здравомыслящие люди довольно быстро осознали, что с датасетами связываться не стоит VD>>На мой взгляд датасэты — это хорошая идея опошленная плохой реализацией.
_FR>Какая именно идея в них хороша и что в реализации подкачало?
Основная — материализация реляционных данных и передача их как единого блока с возможностью последующей обработки. Полезно, что в датасетах можно хранить набор связанных данных, а не просто список. Плохо, то что они не типизированные, типизированные обертки слишком кривые (во всю нарушают принципы инкапсуляции).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: LINQ vs Store Procedure
От:
Аноним
Дата:
23.03.09 12:27
Оценка:
Здравствуйте, VladD2, Вы писали:
VD>Я этим убожеством пользоваться так и не смог. Слишком много неудобств.
Надо себя заставлять.
VD>Какой компиляции? Вот с linq-ом я набираю запрос и вижу список ошибок.
И там тоже самое — вводите несуществующее поле из таблицы — получаете список ошибок.
VD>А что происходит при изменении TSQL-кода?
Проверка на синтакис, естественно.
Проект точно также можно собрать, только выходным файлом будет не .EXE, .SQL
Если в коде есть ошибки, то проект не соберется.
VD>А что на счет динамического SQL который в TSQL не редко появляется и почти не нужен в случае linq.
Эээ, но динамический Linq запрос тоже можно загнать в строку и исполнять во время выполнения программы.
Естественно, Visual Studio не будет проверять синтаксис в строке.
VD>Что до контроля версий, то лично я предпочитаю SVN. Как это чудо с ним скрестить?
Также как проекты на C#, VB и т.д.
Здравствуйте, Аноним, Вы писали:
А>Проверка на синтакис, естественно.
А если ошибка не в синтаксисе? Скажем где-то ошибка в типах данных?
Сам SQL Server не делает никаких проверок до выполнения процедуры. Не уж-то интеграция их делает лучше сервера?
VD>>А что на счет динамического SQL который в TSQL не редко появляется и почти не нужен в случае linq. А>Эээ, но динамический Linq запрос тоже можно загнать в строку и исполнять во время выполнения программы.
Это не так просто. И, главное, этого просто не надо делать. Линковские запросы отлично дополняются и изменяются будучи статически типизированными.
А>Естественно, Visual Studio не будет проверять синтаксис в строке.
И где же преимущества? В лике я имею проверки во время компиляции и гибкость которую в TSQL может дать только динамическая генерация кода.
VD>>Что до контроля версий, то лично я предпочитаю SVN. Как это чудо с ним скрестить? А>Также как проекты на C#, VB и т.д.
Проекты C#, VB и т.д. — это текстовые файлы. А вот хранимки имеют дурацкую особенность храниться в сервере. И их можно править прямо там.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
_FR>>>>Все здравомыслящие люди довольно быстро осознали, что с датасетами связываться не стоит VD>>>На мой взгляд датасэты — это хорошая идея опошленная плохой реализацией.
_FR>>Какая именно идея в них хороша и что в реализации подкачало?
VD>Основная — материализация реляционных данных
Что ты понимаешь под "материализация"? Представление в пользовательском коде?
VD>и передача их как единого блока с возможностью последующей обработки. Полезно, что в датасетах можно хранить набор связанных данных, а не просто список.
Как на счёт других функцианальных возможностей, которые предоставляет датасет? Индексы? View? Биндинг? Сериализация (бинарная и xml)? Они нужны?
VD>Плохо, то что они не типизированные, типизированные обертки слишком кривые (во всю нарушают принципы инкапсуляции).
Ага, что примечательно, с каждой новой версией фреймворка типизированные обёртки понемногу меняются: добавляются новые, недоступные ранее ранее, возможности
Help will always be given at Hogwarts to those who ask for it.
А>>Естественно, Visual Studio не будет проверять синтаксис в строке. VD>И где же преимущества? В лике я имею проверки во время компиляции и гибкость которую в TSQL может дать только динамическая генерация кода.
Влад, у нас есть такие запросы огромные что их будет очень тяжело переписать на linq2sql. И ты не учитываешь что существует легаси код, с большим количеством стор.
Тем более мне обсолютно непонятен linq2sql roadmap.
Здравствуйте, VladD2, Вы писали:
А>>В Visual Studio есть тип проекта для базы данных SQL Server.
VD>Я этим убожеством пользоваться так и не смог. Слишком много неудобств.
Здравствуйте, _FRED_, Вы писали:
_FR>Что ты понимаешь под "материализация"? Представление в пользовательском коде?
Копирование всех данных и обрубание какой-бы то ни было связи.
_FR>Как на счёт других функцианальных возможностей, которые предоставляет датасет? Индексы? View? Биндинг? Сериализация (бинарная и xml)? Они нужны?
Да. Но самое полезное это возможность офлайнт-обновления данных. Меняешь себе данные в датасете, далее получаешь снимок изменений и отправляешь на сервер, где они превращаются в набор запросов.
_FR>Ага, что примечательно, с каждой новой версией фреймворка типизированные обёртки понемногу меняются: добавляются новые, недоступные ранее ранее, возможности
Я бы на их месте придумал что-то вроде датасетов связанных с линком. Так чтобы внутри хранились типизированные объекты (возможно анонимные типы), но при этом были все перечисленные возможности.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Lloyd, Вы писали:
VD>>Я этим убожеством пользоваться так и не смог. Слишком много неудобств.
L>А что с ним не так?
Проще спросить "что так?". Я поставил точку прерывания и попытался отладить хранимку. Получил набор дерганий после чего хранимка выполнилась до конца, то пошагово я ее так пройти и не смог.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>А если ошибка не в синтаксисе? Скажем где-то ошибка в типах данных?
Ну это пока вторая версия интеграции.
Ловит синтаксис и ошибки в названиях полей, таблиц, процедур.
К третьей версии может и Warning на не тот тип прикрутят.
Хотя надо понимать, что SET @Integer_Variable = '123' спокойно проходит в T-SQL.
VD>Сам SQL Server не делает никаких проверок до выполнения процедуры. Не уж-то интеграция их делает лучше сервера?
Ну а что такого? Наверное на C# или VB.NET её и написали, что дало больше возможностей.
VD>Это не так просто. И, главное, этого просто не надо делать. Линковские запросы отлично дополняются и изменяются будучи статически типизированными.
Да-да, я сам сторонник Linq'а.
Но и в SQL есть возможности для дополнений и изменений без генерации динамического SQL.
Ну конечно эти возможности не такие широкие как в Linq.
VD>И где же преимущества? В лике я имею проверки во время компиляции и гибкость которую в TSQL может дать только динамическая генерация кода.
Эээ, кажется я упоминал, что я сам сторонник Linq'а?
Поэтому не надо меня агитировать за него.
Я к тому, что и T-SQL + Visual Studio весьма не плох.
Как раз потому, что проверка во время компиляции есть и в T-SQL.
VD>Проекты C#, VB и т.д. — это текстовые файлы. А вот хранимки имеют дурацкую особенность храниться в сервере. И их можно править прямо там.
И проект базы данных тоже текстовый файл.
А хранимая процедура это не проект, а файл в проекте.
Также как файл с описанием класса на C#, VB.NET и т.д.
И полученный из них EXE файл, тоже можно поправить разнообразными редакторами IL кода, также как и процедуру на сервере. А можно текст хранимой процедуры зашифровать, тогда поправить его руками недоброжелателей не удасться. Ну и можно просто права на правку недоброжелателям не давать.
Здравствуйте, Аноним, Вы писали:
А>Хотя надо понимать, что SET @Integer_Variable = '123' спокойно проходит в T-SQL.
Это по-твоему хорошо?
VD>>Сам SQL Server не делает никаких проверок до выполнения процедуры. Не уж-то интеграция их делает лучше сервера? А>Ну а что такого? Наверное на C# или VB.NET её и написали, что дало больше возможностей.
Такого конечно ничего. Ну, хранимка глючная в БД. Мелочи...
Это ведь лучше чем линг?
VD>>Это не так просто. И, главное, этого просто не надо делать. Линковские запросы отлично дополняются и изменяются будучи статически типизированными. А>Да-да, я сам сторонник Linq'а. А>Но и в SQL есть возможности для дополнений и изменений без генерации динамического SQL.
Есть. Но очень убогие и в конечном итоге они приведут к плохим планам запросов. Причины я тут уже 10 раз объяснил.
А>Ну конечно эти возможности не такие широкие как в Linq.
Ну, а зачем тогда все в хранимки переписывать?
Смотри что получается.
1. Усложняем себе жизнь.
2. Создаем фронт работ на ровном месте.
3. Снижаем надежность системы.
И ради чего все это? Даже не ради ручных оптимизаций, а ради компилированности планов запросов которые и так отлично компилируются.
А>Я к тому, что и T-SQL + Visual Studio весьма не плох. А>Как раз потому, что проверка во время компиляции есть и в T-SQL.
Вроде бы ты сам сказал, что не полная проверка. В общем, это хорошо конечно что что-то сделали для поддержки TSQL. Но сам TSQL это еще то дерьмо. И я бы постарался с ним связываться по реже. Только в случае крайней необходимости.
А>И проект базы данных тоже текстовый файл.
Да ну? А данные тоже в тексте хранить будем?
А>А хранимая процедура это не проект, а файл в проекте. А>Также как файл с описанием класса на C#, VB.NET и т.д. А>И полученный из них EXE файл, тоже можно поправить разнообразными редакторами IL кода, также как и процедуру на сервере. А можно текст хранимой процедуры зашифровать, тогда поправить его руками недоброжелателей не удасться. Ну и можно просто права на правку недоброжелателям не давать.
Хранимку совершенно естественно править из БД. И это часто делают на практике. А часто ли ты правил сборки?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
А>>Хотя надо понимать, что SET @Integer_Variable = '123' спокойно проходит в T-SQL.
VD>Это по-твоему хорошо?
По-моему это может усложнить проверку типа во время компиляции.
VD>>>Сам SQL Server не делает никаких проверок до выполнения процедуры. Не уж-то интеграция их делает лучше сервера? А>>Ну а что такого? Наверное на C# или VB.NET её и написали, что дало больше возможностей.
VD>Такого конечно ничего.
Ну а что такого, относится к удивлению, что интеграция лучше сервера в чем-то.
VD>Это ведь лучше чем линг?
Чем интересно? Проект базы данных и Linq вещи достаточно ортогональные.
Вот у меня в текущем проекте и проект базы данных и Linq.
Все хранится в системе контроля версий, при переименовании колонки, выдаются подсказки, где эта колонка использовалась.
Есть и Unit-тесты на базу данных.
База данных может развертываться и для разработчика, и для тестировщика и для заказчика.
И большая часть этого именно благодаря проекту баз данных. А Linq работает непосредственно в приложении.
VD>Есть. Но очень убогие и в конечном итоге они приведут к плохим планам запросов. Причины я тут уже 10 раз объяснил.
Сомнительно, что все настолько ужасно. Но не будем углубляться.
VD>Ну, а зачем тогда все в хранимки переписывать?
Действительно зачем? Сколько раз мне надо еще написать что я сторонник Linq?
Собственно, у меня в текущем проекте всего около пяти хранимых процедур. На 40 таблиц.
VD>Смотри что получается. VD>1. Усложняем себе жизнь.
Облегчаем себе жизнь. VD>2. Создаем фронт работ на ровном месте.
Уменьшаем количество работы. VD>3. Снижаем надежность системы.
Увеличиваем легкость развертывания и совместной работы нескольких разработчиков.
VD>И ради чего все это? Даже не ради ручных оптимизаций, а ради компилированности планов запросов которые и так отлично компилируются.
Лично мне компилированность планов запросов не сильно важна. А важно удобство всего процесса разработки в большой команде.
VD>Вроде бы ты сам сказал, что не полная проверка. В общем, это хорошо конечно что что-то сделали для поддержки TSQL. Но сам TSQL это еще то дерьмо. И я бы постарался с ним связываться по реже. Только в случае крайней необходимости.
Ладно, чувствую надо уже начинать защищать T-SQL.
У него огромное преимущество — он проще чем С# или VB.NET.
Тестировщика со знанием SQL найти или быстро обучить не сложно.
А со знанием C# или VB.NET тяжело сделать тестировщиком.
Бизнес-аналитики тоже часто знакомы с SQL по роду своей деятельности.
Я уж молчу про сторону заказчика.
VD>Да ну? А данные тоже в тексте хранить будем?
Что мешает хранить справочные данные именно в текстовом файле. INSERT INTO Table(Name) VALUES('')
Да собственно можно и в XML, и MDB, и XLS.
И заполнять из них таблицы при развертывании.
У текстовых данных преимущество, что можно отслеживать изменения в системе контроля версий.
VD>Хранимку совершенно естественно править из БД. И это часто делают на практике. А часто ли ты правил сборки?
Хранимку естественно править из Visual Studio, также как и класс на C# или VB.
Потом компиляция и развертывание на тестовый сервер приложений для прогона Unit-тестов.
Здравствуйте, Аноним, Вы писали:
А>>>Хотя надо понимать, что SET @Integer_Variable = '123' спокойно проходит в T-SQL. VD>>Это по-твоему хорошо? А>По-моему это может усложнить проверку типа во время компиляции.
Проверку это только упростит. А вот надежность кода понизит.
А>Ну а что такого, относится к удивлению, что интеграция лучше сервера в чем-то.
Я еще не видел, чтобы интеграция работала лучше компилятора. У него и времени больше, и проблем меньше.
А>Все хранится в системе контроля версий, при переименовании колонки, выдаются подсказки, где эта колонка использовалась.
Лучше бы чтобы все автоматом менялось.
А>Есть и Unit-тесты на базу данных.
Гы. Любимый аргумент любителей скриптов. "А у нас юнит-тесты есть".
Есть такой анекдот:
— А у нас есть свобода!
— А у нас Леонид Ильич Брежнев!
— А у нас есть колбаса!
— А у нас Леонид Ильич Брежнев!
— А мы у вас его украдем!
— Тогда и у вас колбасы не будет.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, baranovda, Вы писали:
B>На выборку данных эти оба великолепно спариваются. B>Из IQueryable получаем IDbCommand, из IDbCommand — IDbDataReader, а последним заполняем DataTable.
Речь не о чтении данных. Речь об идеологии. В датасетах хорошо — отсоедененность и автономная работа, плохо — нетипизированнойсть и запутанность АПИ.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Как сделано у нас — не могу. Как делается самостоятельно (сорри что невнятно — по памяти. давно решалось):
1) Вы можете использовать в качестве кодогенератора что угодно — тот же reegenerator (http://www.reegenerator.com/Features.htm). T4 мне больше нравится
2) Читаем вводную статью, например — http://www.olegsych.com/2007/12/text-template-transformation-toolkit/. В ней куча самплов. Для DataSet'a нет. Если не находится (мне проще было написать своё — специфика):
3) Общая идея T4 — если нам надо что-то сложнее чем подстановка имени класса — генерим строку и скармливаем через this.WriteLine. Всё что нам надо — превратить xsd датасета в текст. Что использовать — XSLT, собственный быдлокод+XmlReader или CodeDom — на ваше усмотрение.
Не, давайте уж разбираться
G>Смотрю сгенерированные EF классы — оповещения будут.
Это оповещения на изменение свойств элемента. Они хороши для биндинга к конкретной сущности. Попробуйте отследить добавление/удаление/изменение любой сущности — причём именно те, что будут отражены в базе. У ObjectContext только одно событие — SavingChanges. Вы конеш можете проводить валидацию внутри сущностей, но это во-первых намекает о жирной модели. Во-вторых, вы не сможете так проверять сложные ограничения, что требуют доступа ко всему контексту. Или хотя бы отследить тот факт, что сущность поменяла родителя
Кстати, попробуйте реализовать ограничение на уникальность любого поля. EDM позволяет определить только один Key. Даже элементарное требование несуществования двух сущностей с одинаковыми именами уже требует приседаний. Напомню — нарушение ограничений должно обнаруживаться при попытке изменения сущности, чтобы можно было его отловить и исправить на месте. Вы внимательней присмотритесь к EDM. Как средство описания модели данных она довольно убога.
G>Для работы с графами объектов в UI я бы тоже рекомендовал viewmodel создавать.
1) мы всё ещё обсуждаем десктоп клиента? основное предназначение DAL здесь — данные для биндинга к UI + чуть-чуть логики. Фактически, процентов так 90 требуемого функционала придётся писать ручками.
2) Под ViewModel вы понимаете кучу классов-обёрток, что изображают из себя сущности/коллекции, а на практике работают с контекстом? Если да — то мы говорим ровно об одном и том же — в чистом виде EF непригоден для использования для биндинга. Кстати, реализовывать интерфейсы, нужные для биндинга — такой гемморой...
G>Ну если рассматривать только десктоп-клиент с непосредственным доступом в базу, то вооще зачем нужен disconnected режим? G>Если многозвенное приложение, то рецепт я привел выше.
Даже если у нас многозвенное _intranet_ приложение, то лучше использовать tcp endpoints ч/з WCF. REST для локальной сети — оверкилл в квадрате. Disconnected режим нужен для одной простой вещи — масштабируемости. Вы имели счастье наблюдать, как один полумёртвый celeron 1.8/512ram не задыхаясь держит нагрузку, необходимую для _одновременного_ обслуживания 200 пользователей? При Disconnected режиме эти 200 одновременных соединений вполне себе превращаются в пару тысяч клиентов — это с учётом боттлнеков по утрам, т.к. обращения к базе нужны, когда надо сохранить/обновить данные/выполнить нетривиальные операции типа полнотекстового поиска. Обычно работа с сервером не затягивается дольше чем на пару секунд. В среднем пользователь обращается за повторными сведениями раз в 10 минут (это средняя температура по больнице, сами понимаете). Эффективность сами посчитаете?
Естественно, для time-critical-data прямые обращения к серверу удобнее. Но это совсем отдельная тема.
G>Многие решения по работе с данными отдают костылями.
Ага. но датасеты _на десктоп-клиенте_ какие-то менее костылятые.
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, gandjustas.
S>Не, давайте уж разбираться
G>>Смотрю сгенерированные EF классы — оповещения будут. S>Это оповещения на изменение свойств элемента. Они хороши для биндинга к конкретной сущности. Попробуйте отследить добавление/удаление/изменение любой сущности — причём именно те, что будут отражены в базе. У ObjectContext только одно событие — SavingChanges. Вы конеш можете проводить валидацию внутри сущностей, но это во-первых намекает о жирной модели. Во-вторых, вы не сможете так проверять сложные ограничения, что требуют доступа ко всему контексту. Или хотя бы отследить тот факт, что сущность поменяла родителя
Это все требует вытягивания большого количества данных в память. По соображениям производительности такого лучше не делать, при небольшой нагрузке на приложение база начнет загибаться.
S>Кстати, попробуйте реализовать ограничение на уникальность любого поля. EDM позволяет определить только один Key. Даже элементарное требование несуществования двух сущностей с одинаковыми именами уже требует приседаний. Напомню — нарушение ограничений должно обнаруживаться при попытке изменения сущности, чтобы можно было его отловить и исправить на месте.
!context.Table.Any(e => e.Name == "xxx")
???
Сомневаюсь что датасеты сделают это лучше.
S>Вы внимательней присмотритесь к EDM. Как средство описания модели данных она довольно убога.
Многие недостатки исправят во второй версии EF, остается только ждать.
G>>Ну если рассматривать только десктоп-клиент с непосредственным доступом в базу, то вооще зачем нужен disconnected режим? G>>Если многозвенное приложение, то рецепт я привел выше.
S>Даже если у нас многозвенное _intranet_ приложение, то лучше использовать tcp endpoints ч/з WCF. REST для локальной сети — оверкилл в квадрате.
С чего бы? Как раз в локльной сети оверхеда и незаметно будет.
Учитывая возможности кеширования HTTP можно сделать так, чтобы суммарный трафик оказался меньше.
S>Disconnected режим нужен для одной простой вещи — масштабируемости. Вы имели счастье наблюдать, как один полумёртвый celeron 1.8/512ram не задыхаясь держит нагрузку, необходимую для _одновременного_ обслуживания 200 пользователей? При Disconnected режиме эти 200 одновременных соединений вполне себе превращаются в пару тысяч клиентов — это с учётом боттлнеков по утрам, т.к. обращения к базе нужны, когда надо сохранить/обновить данные/выполнить нетривиальные операции типа полнотекстового поиска. Обычно работа с сервером не затягивается дольше чем на пару секунд. В среднем пользователь обращается за повторными сведениями раз в 10 минут (это средняя температура по больнице, сами понимаете). Эффективность сами посчитаете?
Открытый контекст EF не заставляет держать открытое соединение.
G>>Многие решения по работе с данными отдают костылями. S>Ага. но датасеты _на десктоп-клиенте_ какие-то менее костылятые.
Мне кажется что вы просто не умеете готовить EF.
Здравствуйте, gandjustas.
G>Это все требует вытягивания большого количества данных в память. По соображениям производительности такого лучше не делать, при небольшой нагрузке на приложение база начнет загибаться.
0) почему база-то будет загибаться??? ей практически всё равно сколько данных отдавать, если они хорошо нормализованы и хороший index coverage. Скорее наоборот, куча мелких обращений обойдётся дороже.
1) у нас всё ещё десктоп клиент, так? В память выгребаются только данные, нужные клиенту. От пары тысяч сущностей он загнётся?
2) Ограничения пишутся не от балды — они отражают существенные связи в предметной области. Как правило, ограничения, что проверяются на клиенте значимы для проведения конкретных бизнес-операций. Естественно ограничения на клиенте не служат для _защиты_ от несогласованных данных — это обязанность субд. Они нужны для _раннего обнаружения_ ошибок. В разницу будем углубляться?
3) Объём данных, необходимых для проведения конкретной бизнес-операции обычно небольшой — допустим, у нас не может быть одинаковых категорий продуктов. Список категорий обычно достаточно небольшой и его удаётся кэшировать на клиенте. В случае, когда это недопустимо — либо дёргаем базу, либо забиваем на препроверки и сосредотачиваемся на интерактивном мерже при обнаружении конфликтов.
G>
G>!context.Table.Any(e => e.Name == "xxx")
G>
G>???
1) Вы проверяете наличие элемента с таким именем в базе, не в контексте. Если вы удалили сущность в контексте — ограничение покажет лодную информацию.
2) Вы обязаны вызывать эту проверку _во всех_ методах, обращающихся к e.Name/добавляющих новый объект в контекст. В том числе и внутри биндинга — вам уже нужны сторонние обёртки.
3) У вас идёт обращение к серверу на каждое изменение имени. Если у вас массовые обновления/вставки — сервер загнётся.
4) даже если вы выгрузите сущности в список, вам придётся синхронизировать измсенения в контексте и в списке — чтобы не было противоречий.
G>Сомневаюсь что датасеты сделают это лучше.
Вызывается _один_ раз в конструкторе. Генерится дизайнером. Используются индексы на rbtree.
S>>Вы внимательней присмотритесь к EDM. Как средство описания модели данных она довольно убога. G>Многие недостатки исправят во второй версии EF, остается только ждать.
Ну, фундаментально нового ничего не обещано. Из интересного — интеллектуальный маппинг, computed columns, edm-defined functions. Но да, с интересом ждём.
S>>Даже если у нас многозвенное _intranet_ приложение, то лучше использовать tcp endpoints ч/з WCF. REST для локальной сети — оверкилл в квадрате. G>С чего бы? Как раз в локльной сети оверхеда и незаметно будет. G>Учитывая возможности кеширования HTTP можно сделать так, чтобы суммарный трафик оказался меньше.
У нас допустим дедлок именно в пропускной способности сети был.
Кэширование не спасёт. В локальной сети пользователи — не обезьянки, что выгребают горы одинакового трафа. Они гребут данные, что нужны им для работы, и данные пересекаются безумно редко. посему — сорри
G>Открытый контекст EF не заставляет держать открытое соединение.
Мы ведь обсуждали выгоды disconnected mode вроде? Как-то вы с темы на тему перескакиваете. Тем не менее:
1) если у вас регулярные проверки типа той что написана выше — требует.
2) если у вас свой локальный кэш — всё ок. Другое дело, что с ef локальный кэш приходится писать ручками.
G>Мне кажется что вы просто не умеете готовить EF.
Дык поделитесь рецептами
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, gandjustas.
G>>Это все требует вытягивания большого количества данных в память. По соображениям производительности такого лучше не делать, при небольшой нагрузке на приложение база начнет загибаться.
S>0) почему база-то будет загибаться??? ей практически всё равно сколько данных отдавать, если они хорошо нормализованы и хороший index coverage. Скорее наоборот, куча мелких обращений обойдётся дороже. S>1) у нас всё ещё десктоп клиент, так? В память выгребаются только данные, нужные клиенту. От пары тысяч сущностей он загнётся?
Ну вариант один клиент — одна база и рассматривать по большому счету не стоит. В таких случаях можно держать SqlCE базу и работать с resultset_ами, напрямую смотрящими в таблицу.
Если у вас несколько клиентов смотрят в одну базу, то вам все равно придется проверять актуальность локальных копий и частенько гонять change-setы туда-сюда.
S>2) Ограничения пишутся не от балды — они отражают существенные связи в предметной области. Как правило, ограничения, что проверяются на клиенте значимы для проведения конкретных бизнес-операций. Естественно ограничения на клиенте не служат для _защиты_ от несогласованных данных — это обязанность субд. Они нужны для _раннего обнаружения_ ошибок. В разницу будем углубляться?
Я в курсе какие ограничения зачем пишутся. Но это не отметает необходимости загружать много данных из базу для проверки некоторых из них.
S>3) Объём данных, необходимых для проведения конкретной бизнес-операции обычно небольшой — допустим, у нас не может быть одинаковых категорий продуктов. Список категорий обычно достаточно небольшой и его удаётся кэшировать на клиенте. В случае, когда это недопустимо — либо дёргаем базу, либо забиваем на препроверки и сосредотачиваемся на интерактивном мерже при обнаружении конфликтов.
Ну это если один клиент на одну базу.
G>>
G>>!context.Table.Any(e => e.Name == "xxx")
G>>
G>>???
S>1) Вы проверяете наличие элемента с таким именем в базе, не в контексте. Если вы удалили сущность в контексте — ограничение покажет лодную информацию.
После каждого изменения данных их хорошо бы в базу писать, а то приложение упасть может свет вырубят и пр. Желательно чтобы по нажатию "сохранить" изменения дествительно сохранялись.
Проверка нужна непосредственно перед сохранением, чтобы красивый feedback обеспечить.
S>2) Вы обязаны вызывать эту проверку _во всех_ методах, обращающихся к e.Name/добавляющих новый объект в контекст. В том числе и внутри биндинга — вам уже нужны сторонние обёртки.
С чего это я обязан такое делать? Мне вполне хватит чтобы невалидные данные в базу не попали, для этого в принцие ничего кроме ограниченй в базе и не надо. Дополнительная проверка делается только для целей UI.
А уже в binding она нафиг не нужна.
S>3) У вас идёт обращение к серверу на каждое изменение имени. Если у вас массовые обновления/вставки — сервер загнётся.
Нет, обращения к серверу идут когда я вызываю SaveChanges, обычно это нажатие кнопки "Сохранить" или чего-то в этом роде.
S>4) даже если вы выгрузите сущности в список, вам придётся синхронизировать измсенения в контексте и в списке — чтобы не было противоречий.
Не нужно будет. Элементами списка будут являться теже сущности, что и в контексте.
G>>Сомневаюсь что датасеты сделают это лучше. S>
S>Вызывается _один_ раз в конструкторе. Генерится дизайнером. Используются индексы на rbtree.
Ну я в курсе, но как это гарантирует согласованность в БД при наличии нескольких клиентов?
S>>>Вы внимательней присмотритесь к EDM. Как средство описания модели данных она довольно убога. G>>Многие недостатки исправят во второй версии EF, остается только ждать. S>Ну, фундаментально нового ничего не обещано. Из интересного — интеллектуальный маппинг, computed columns, edm-defined functions. Но да, с интересом ждём.
S>>>Даже если у нас многозвенное _intranet_ приложение, то лучше использовать tcp endpoints ч/з WCF. REST для локальной сети — оверкилл в квадрате. G>>С чего бы? Как раз в локльной сети оверхеда и незаметно будет. G>>Учитывая возможности кеширования HTTP можно сделать так, чтобы суммарный трафик оказался меньше.
S>У нас допустим дедлок именно в пропускной способности сети был.
При передачи датасетов — я не сомневаюсь. Сам видел такое в одном проекте.
S>Кэширование не спасёт. В локальной сети пользователи — не обезьянки, что выгребают горы одинакового трафа. Они гребут данные, что нужны им для работы, и данные пересекаются безумно редко. посему — сорри
Клиентское кеширование, пользователь не будет много раз тянуть неизменяющиеся сущности. Суммарная нагрузка на сервер по траффику вполне может оказаться гораздо ниже, чем через WCF даже с бинарной сериализацией.
G>>Открытый контекст EF не заставляет держать открытое соединение. S>Мы ведь обсуждали выгоды disconnected mode вроде? Как-то вы с темы на тему перескакиваете. Тем не менее: S>1) если у вас регулярные проверки типа той что написана выше — требует.
Про сохранение данных я писал выше.
S>2) если у вас свой локальный кэш — всё ок. Другое дело, что с ef локальный кэш приходится писать ручками.
С чего вы взяли? сам по себе контекст EF обеспечивает локальный кеш.
G>>Мне кажется что вы просто не умеете готовить EF. S>Дык поделитесь рецептами
1)Для работы контекста совершенно необязательно держать открытым соединение. Нужно закрыть — context.Connection.Close();
2)Объекты из кеша контекста можно получить так:
from se in context.ObjectStateManager.GetObjectStateEntries(EntityState.Unchanged | EntityState.Modified | EntityState.Added)
where !se.IsRelationship
select se.Entity;
Допилить по вкусу.
3)Чтобы получить объекты без кеширования в контексте можно Linqовый запрос привести к типу ObjectQuyery<T> и вызывать Execute(MergeOption.NoTracking)
Здравствуйте, VladD2, Вы писали:
VD>Вань, а что же они у нас то не рулят на сервере?
Потому что их там нет, а те что есть — сам знаешь как писались...
VD>IT тут недавно рассказывал, что он какой-то там кусок на сервере переписал с использованием линка и скорость выросла в несколько раз.
Могу наспор переписать этот же кусок кода на хранимке, чтобы работал как минимум так же (другое дело, что думать придется) и могу придумать такой сценарий, что никакой линк не поможет... Ты это к чему собственно?
VD>Какое-то расхождение теории и практики.
Ты просто не внимательно читаешь. Речь не о хранимка vs линк, а о хранимка vs триггер. Я сам из нашей базы часть триггеров вычищал, лет несколько назад, когда она в очередной раз колом встала.
Про линки и запросы из кода — отдельный разговор.
Здравствуйте, VladD2, Вы писали:
VD> Нужно просто понимать одну простую вещь. MS SQL кэширует планы к запросам очень тупо.
Ты даже не представляешь, насколько умно он это делает.. =)
VD>Так вот генерируя динамически запросы от вас требуется делать так, чтобы они были одинаковыми.
Строго говоря, это не так. Все существенно сложнее и от этих мелочей довольно много зависит.
Откуда взялась идея, что у нас "один клиент-одна база"? Если из-за "В память выгребаются только данные, нужные клиенту" — мои извинения, конечно же имелась в виду память клиента.
G>Если у вас несколько клиентов смотрят в одну базу, то вам все равно придется проверять актуальность локальных копий и частенько гонять change-setы туда-сюда.
1) не совсем. изменяемые данные практически не пересекаются — это вопрос эффективномти организации работы пользователей. Как только у вас несколько пользователей начинает править одну и ту же информацию — смело топайте к заказчику и начинайте обсуждать эффективность организации трудового процесса
2) изменения вносимые пользователями как правило затрагивают кучу сущностей и не вносятся по частям из-за ограничений в субд. Точно так же их нельзя вытаскивать по частям. Поэтому чанжсеты гонять придётся всё равно. Точнее, в СУБД отправляются только изменённые данные, назад выгребаются данные целиком: из-за небольшого объёма данных получается быстрее и проще, чем кидать изменения с последней синхронизации и затем их мержить.
3) Регулярная синхронизация по таймеру неудобна пользователям. Проще дать им знакомую концепцию "открыть/сохранить", и предупреждать о потере информации/проводить обновление по требованию. Естественно, есть corner cases, когда нужно "данные сейчас", но это отдельная тема.
G>После каждого изменения данных их хорошо бы в базу писать, а то приложение упасть может свет вырубят и пр. Желательно чтобы по нажатию "сохранить" изменения дествительно сохранялись. G>Проверка нужна непосредственно перед сохранением, чтобы красивый feedback обеспечить.
Извините, я сейчас буду сильно ругаться и брызгать слюнями Вы программы для менеджеров пишете? Для красивых отчётов? Пользователям нафиг сдался красивый фидбак и программа. Они работают. Не с вашей программой, а делают свою работу. Программа — только инструмент — это она должна подстраиваться под пользователей. Если он допустил ошибку — программа должна помочь её исправить сразу же. Это всё равно что говорить что спеллчекер нужен для красивого фидбака при сохранении.
Потеря информации не решается программой с мгновенными сохранениями. Здесь нужен упсилятор и кошерный электрик. Мгновенные сохранения мешают пользователям — они вынуждены _постоянно_ контролировать свои действия, что повышает утомляемость. Естественный режим работы — правка-проверка-синхронизация. Это же азы дизайна UI, даже в университетах подобное в рамках курса ЧМВ (человеко-машинное взаимодействие) читается. Как вы пишете UI —
G>С чего это я обязан такое делать? Мне вполне хватит чтобы невалидные данные в базу не попали, для этого в принцие ничего кроме ограниченй в базе и не надо. Дополнительная проверка делается только для целей UI. G>А уже в binding она нафиг не нужна.
Выше уже сказано про мгновенные сохранения. У нас просто разный подход к написанию систем: для меня попытка записать некорректные данные в базу — ЧП + баг в клиенте. Если бы не было ограничения, данные в базе были бы повреждены, система неработоспособна. Всё.
G>Ну я в курсе, но как это гарантирует согласованность в БД при наличии нескольких клиентов?
Уже писалось. Ограничения на сервере и на клиенте выполняют разные роли. На сервере — последний спасательный круг, средство для отлова багов клиента. На клиенте — средство раннего отлова багов пользователя. Зачем надо — тоже писалось выше.
S>>У нас допустим дедлок именно в пропускной способности сети был. G>При передачи датасетов — я не сомневаюсь. Сам видел такое в одном проекте.
У нас не было передачи датасетов. У нас была передача tds от СУБД к клиентам процессор-память простаивали на треть, жёсткий почти на пределе, 100 мбит сеть — фсё (по таск манадждеру ~ 60-70%, по перфмону — дикая очередь пакетов).
G>Клиентское кеширование, пользователь не будет много раз тянуть неизменяющиеся сущности. Суммарная нагрузка на сервер по траффику вполне может оказаться гораздо ниже, чем через WCF даже с бинарной сериализацией.
Писал выше. Когда сущности нормализованы, отслеживание изменений/формирование чанжсета/мерж оказываются дороже простой заливки данных с нуля. Проверено неоднократно.
S>>2) если у вас свой локальный кэш — всё ок. Другое дело, что с ef локальный кэш приходится писать ручками. G>С чего вы взяли? сам по себе контекст EF обеспечивает локальный кеш. G>2)Объекты из кеша контекста можно получить так: G>
G>from se in context.ObjectStateManager.GetObjectStateEntries(EntityState.Unchanged | EntityState.Modified | EntityState.Added)
G>where !se.IsRelationship
G>select se.Entity;
G>
G>Допилить по вкусу.
На выходе имеем мешанину из сущностей различных типов, причём отслеживать изменения в контексте невозможно. Кэш нельзя использовать для удобной выборки локальных данных, для валидации при изменениях и для биндинга. Зачем он нужен в десктоп-клиенте?
У нас просто слишком разные подходы к написанию софта. Предлагаю закругляться. Спасибо за альтернативный взгляд
Здравствуйте, Sinix, Вы писали:
S>Потеря информации не решается программой с мгновенными сохранениями. Здесь нужен упсилятор и кошерный электрик. Мгновенные сохранения мешают пользователям — они вынуждены _постоянно_ контролировать свои действия, что повышает утомляемость. Естественный режим работы — правка-проверка-синхронизация. Это же азы дизайна UI, даже в университетах подобное в рамках курса ЧМВ (человеко-машинное взаимодействие) читается. Как вы пишете UI —
Естественный режим — это постоянное сохраенение + возможность отката до преидущих версий. Пользователи пищат от радости
Здравствуйте, Sinix, Вы писали:
C>>Естественный режим — это постоянное сохраенение + возможность отката до преидущих версий. Пользователи пищат от радости S>+1 S>Вы имеете в виду возможность отмены изменений, сделанных в текущем сеансе редактирования? Или отмену любого изменения за время существования системы?
В идеале — и то, и другое.
S>Первое вполне реализуемо — хотя бы фоновым бэкапом кэша. Второе — сами понимаете. S>Интересная тема конеш, но так мы скатимся к темпоральным базам и дизайну гуя для них. Есть ещё какие замечания?
Есть, но лень писать
В частности, все известные мне схемы общения с БД из десктопного клиента дохнут в тех или иных сценариях при работе через высоколатентные сети (Интернет).
Здравствуйте, Cyberax.
C>В частности, все известные мне схемы общения с БД из десктопного клиента дохнут в тех или иных сценариях при работе через высоколатентные сети (Интернет).
Дыкть ничего нового: пара клиентов — впн, филиалы — репликация по впн, anybody — сайт+вебсервисы (опционально впн )
Кстати вариант с partially disconected apps дохлые каналы переносит лучше всего.
Здравствуйте, Sinix, Вы писали:
C>>В частности, все известные мне схемы общения с БД из десктопного клиента дохнут в тех или иных сценариях при работе через высоколатентные сети (Интернет). S>Дыкть ничего нового: пара клиентов — впн, филиалы — репликация по впн, anybody — сайт+вебсервисы (опционально впн )
А чем VPN-то поможет? Он идти будет точно так же через медленные каналы.
Или имеешь в виду VPN + Remote Desktop? Так это неудобно, глючно и сложно. Репликация — это зачастую тоже не решение. Опять же, вопросы с когерентностью данных и контролем доступа начинаются.
S>Кстати вариант с partially disconected apps дохлые каналы переносит лучше всего.
А вот partially disconected-приложения как раз очень плохо дружат с классическими БД.
Здравствуйте, Cyberax C>А чем VPN-то поможет? Он идти будет точно так же через медленные каналы.
Не-не, в смысле что тут ещё изобрести-то можно. Ремот десктоп даже и не рассматривался — он только для файл-серверов хорош.
А из-за чего по вашему мнению бд дохнут и какие варианты не будут дохнуть? Просто интересно что же такого можно наизобретать. Единственная причина что я вижу — затянувшиеся сессии + блокировки. Как уже писалось, partially disconnected резко сокращает число обращений к субд.
C>А вот partially disconected-приложения как раз очень плохо дружат с классическими БД.
Может мы под partially disconected разные вещи понимаем? Я вслед за МС и Сеппой под partially disconected понимаю софтину, которая большую часть времени работает автономно и изредка обращается к СУБД за данными/сохраняет изменения.
Я не въезжаю, почему СУБД с ними дружить не будет.
Если вы про приложения с репликацией в локальную in-memory бд — то они зовутся offline clients вообще-то.
Про репликацию полностью согласен. Тем не менее, какие вы предлагаете варианты по первым двум сценариям (пара удалённых пользователей и филиалы)?
Здравствуйте, Sinix, Вы писали:
S>А из-за чего по вашему мнению бд дохнут и какие варианты не будут дохнуть? Просто интересно что же такого можно наизобретать. Единственная причина что я вижу — затянувшиеся сессии + блокировки. Как уже писалось, partially disconnected резко сокращает число обращений к субд.
Основная проблема — латентность и сравнительно низкая пропускная способность каналов. В локалке часто можно сделать запрос и показать результат без видимой задержки для пользователя. В WAN такое просто не прокатит.
C>>А вот partially disconected-приложения как раз очень плохо дружат с классическими БД. S>Может мы под partially disconected разные вещи понимаем? Я вслед за МС и Сеппой под partially disconected понимаю софтину, которая большую часть времени работает автономно и изредка обращается к СУБД за данными/сохраняет изменения.
Да, у меня немного другое.
S>Я не въезжаю, почему СУБД с ними дружить не будет. S>Если вы про приложения с репликацией в локальную in-memory бд — то они зовутся offline clients вообще-то.
Очень часто надо иметь online-изменения, но при этом хранить локальный кэш на клиенте. Такой сценарий получается очень туго.
S>Про репликацию полностью согласен. Тем не менее, какие вы предлагаете варианты по первым двум сценариям (пара удалённых пользователей и филиалы)?
У меня используется моя система когерентных объектных кэшей на клиентах.
Ага. Теперь понял о чём вы. Сгласен. В принципе решаемо и силами СУБД (back notifies через брокер + timestamps на строках), но получается безумно криво и коряво.
Видимо про UI недопоняли друг друга.
Разделяю вашу точку зрения.
S>>>У нас допустим дедлок именно в пропускной способности сети был. G>>При передачи датасетов — я не сомневаюсь. Сам видел такое в одном проекте.
S>У нас не было передачи датасетов. У нас была передача tds от СУБД к клиентам процессор-память простаивали на треть, жёсткий почти на пределе, 100 мбит сеть — фсё (по таск манадждеру ~ 60-70%, по перфмону — дикая очередь пакетов).
Если пытаться вытягивать кучу связанных сущнстей из БД, то это может превратиться в огромную портянку заджойненых данных.
Передача сериализованных объектов бдет экономичнее.
S>>>2) если у вас свой локальный кэш — всё ок. Другое дело, что с ef локальный кэш приходится писать ручками. G>>С чего вы взяли? сам по себе контекст EF обеспечивает локальный кеш. G>>2)Объекты из кеша контекста можно получить так: G>>
G>>from se in context.ObjectStateManager.GetObjectStateEntries(EntityState.Unchanged | EntityState.Modified | EntityState.Added)
G>>where !se.IsRelationship
G>>select se.Entity;
G>>
G>>Допилить по вкусу.
S>На выходе имеем мешанину из сущностей различных типов, причём отслеживать изменения в контексте невозможно. Кэш нельзя использовать для удобной выборки локальных данных, для валидации при изменениях и для биндинга. Зачем он нужен в десктоп-клиенте?
.OfType ?
Для биндинга и валидации одной сущности и кеш не нужен. Достаточно одного объекта.
Для графа надо создавать отдельный viewmodel.
Здравствуйте, IB, Вы писали:
VD>>Вань, а что же они у нас то не рулят на сервере? IB>Потому что их там нет, а те что есть — сам знаешь как писались...
Как это нет? Их там хватат. А то что написаны... Ну, так за чем дело встало? Или ты о сфероконях в вакуме рассуждал?
Почему-то в форумах все говорят о каких-то идеальных условиях и лучших реализациях, но в жизни почему-то все время встречаются хреновые условиях и посрдственные реализации.
Мне кажется выбирая стратегию разумнее ориентироваться на второе — на жизнь.
VD>>IT тут недавно рассказывал, что он какой-то там кусок на сервере переписал с использованием линка и скорость выросла в несколько раз. IB>Могу наспор переписать этот же кусок кода на хранимке, чтобы работал как минимум так же (другое дело, что думать придется) и могу придумать такой сценарий, что никакой линк не поможет... Ты это к чему собственно?
Зачем не сапор? Перепиши без споров.
В прочем ты не раз оптимизировал код сервера, но он все равно упорно продолжает тормозить.
Я это говорю не чтобы тебя или твоей подход упрекнуть. Я это к тому, что только на словах все просто. По жизни главная проблема в сложности. А она в не малой мере возникает в следствии того, что код плохо структурирован и используются хреновые средства разработки. IT замечательно продемонстрировал, что с помощью линка и грамотного подхода можно резко увеличить производительность.
VD>>Какое-то расхождение теории и практики. IB>Ты просто не внимательно читаешь. Речь не о хранимка vs линк, а о хранимка vs триггер. Я сам из нашей базы часть триггеров вычищал, лет несколько назад, когда она в очередной раз колом встала.
Как раз к триггерам у меня особых вопросов нет. Главное чтобы там не было бизнес-логики (т.е. много логики).
Кстати, а теперь можно писать триггеры на донтете?
IB>Про линки и запросы из кода — отдельный разговор.
Дык тема как раз про линк и перенос этой логики в хранимки. Причем не в виде продуманного решения, а так чтобы компиляцию устранить.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, IB, Вы писали:
VD>> Нужно просто понимать одну простую вещь. MS SQL кэширует планы к запросам очень тупо. IB>Ты даже не представляешь, насколько умно он это делает.. =)
Возможно. А возможно и нет.
Поделись своими мыслями... поглядим.
VD>>Так вот генерируя динамически запросы от вас требуется делать так, чтобы они были одинаковыми. IB>Строго говоря, это не так. Все существенно сложнее и от этих мелочей довольно много зависит.
Понятно, что какие-то там нюансы существуют. Но для понимания общего принципа оно не нужно. А без его понимания люди вот умудряются делая динамические запросы в хранимках получать проигрыш в производительности.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Как это нет?
А вот так. 90% запросов тупо прошиты в коде, в том числе и тот, который IT переписал.
VD>В прочем ты не раз оптимизировал код сервера, но он все равно упорно продолжает тормозить.
Ни я, ни кто другой, никогда не пытались привести там все в порядок, просто лечили наиболее острые проблемы. К чему такой подход приводит вообщем-то очевидно и совершенно не зависит от используемого инструмента и даже области — линк, хранимки, C++, C# — без разницы.
VD> IT замечательно продемонстрировал, что с помощью линка и грамотного подхода можно резко увеличить производительность.
А с этим кто-то спорил?
VD>Как раз к триггерам у меня особых вопросов нет.
А у меня есть. И именно об этом я и писал, а не про линк.
VD>Кстати, а теперь можно писать триггеры на донтете?
В каком смысле? Ты можешь конечно задействовать код написанный на дотнете из триггера, равно как и из любой хранимки, но на практике толку от этого мало.
VD>Дык тема как раз про линк и перенос этой логики в хранимки. Причем не в виде продуманного решения, а так чтобы компиляцию устранить.
Но я этой темы здесь не касался и писал совершенно не об этом.
Здравствуйте, VladD2, Вы писали:
VD>Возможно. А возможно и нет. VD>Поделись своими мыслями... поглядим.
Это на хорошую статью потянет, а они уже написаны. Вот здесь например: http://technet.microsoft.com/ru-ru/library/cc966425(en-us).aspx
VD>Понятно, что какие-то там нюансы существуют. Но для понимания общего принципа оно не нужно.
Ты как-то совсем общий принцип урезал. =)
Здравствуйте, IB, Вы писали:
VD>>Кстати, а теперь можно писать триггеры на донтете? IB>В каком смысле? Ты можешь конечно задействовать код написанный на дотнете из триггера, равно как и из любой хранимки, но на практике толку от этого мало.
Если есть возможность создавать хранимки на дотнете, то было бы логично сделать интерфейс и для создания триггеров на дотнете. То есть, не вызвать дотнетный код из T-SQL-ного триггера, а напрямую подключать метод в качестве обработчика. Что-то типа событий.
Судя по твоей реакции такого нет. А жаль.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Это на буржуйском. Плюс статья явно устарела. Статья 2004 года, а в 2008, как я понимаю как раз в области планов были серьезные изменения.
VD>>Понятно, что какие-то там нюансы существуют. Но для понимания общего принципа оно не нужно. IB>Ты как-то совсем общий принцип урезал. =)
Ты всю ветку читал? Видел на что я отвечал?
Человек не понимает самого общего принципа кэшироания планов. От того сделал вывод, что динамические запросы в хранимках всегда ухудшают производительность. А дело (скорее всего) было в том, что EXEC применялся, а параметры были в код зашиты. В итоге кэшировалось все подряд и толку от такого кэша практически не было.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Если есть возможность создавать хранимки на дотнете, то было бы логично сделать интерфейс и для создания триггеров на дотнете. То есть, не вызвать дотнетный код из T-SQL-ного триггера, а напрямую подключать метод в качестве обработчика. Что-то типа событий.
VD>Судя по твоей реакции такого нет. А жаль.
CREATE TRIGGER trigger_name ON table_name FOR INSERT
AS EXTERNAL NAME assembly_name.class_name.method_name
L>>CREATE TRIGGER trigger_name ON table_name FOR INSERT
L>>AS EXTERNAL NAME assembly_name.class_name.method_name
L>>
VD>А как должен метод выглядеть?
< method_specifier >
For a CLR trigger, specifies the method of an assembly to bind with the trigger. The method must take no arguments and return void. class_name must be a valid SQL Server identifier and must exist as a class in the assembly with assembly visibility. If the class has a namespace-qualified name that uses '.' to separate namespace parts, the class name must be delimited by using [ ] or " " delimiters. The class cannot be a nested class.
Здравствуйте, kenzo_u, Вы писали:
_>Почему фиолетово для квалифицированного разработчика и почему только хранимки для стажеров?
Потому что у квалифицированного DAL будет, а значит где конкретно находятся запросы не столь важно, а у стажера — все равно будет каша, так хоть запросы отдельно лягут, да и руку набивать надо.
Здравствуйте, VladD2, Вы писали:
VD>Ну, так за чем дело встало?
Я последние лет несколько сиквелом не очень плотно занимаюсь.
VD>Это на буржуйском. Плюс статья явно устарела.
Она более чем актуальна.
VD> Статья 2004 года, а в 2008, как я понимаю как раз в области планов были серьезные изменения.
Серьезных не было. Там планомерные улучшения с 2000-й версии.
VD>Ты всю ветку читал? Видел на что я отвечал?
Мнизу вверх, сначало это, а потом то что раньше — по нетбуку совсем не удобно.. )
Здравствуйте, VladD2, Вы писали:
VD>Судя по твоей реакции такого нет. А жаль.
Нет, у меня реакция — "есть но непонятно зачем". На практике такое пожалуй только для поддержки легаси кода нужно, ну или какая-нибудь экзотика...
Здравствуйте, VladD2, Вы писали:
VD>Я еще не видел, чтобы интеграция работала лучше компилятора. У него и времени больше, и проблем меньше.
Я тебе про DBPro еще два года назад рассказывал, ты и тогда не верил, а проверить поленился...
Все очень не плохо работает, те недостатки которые ты описываешь, этот инструмент убирает, правда определенная культура нужна.
А линк, к сожалению не панацея, нельзя весь код на него перенести.
VD>Лучше бы чтобы все автоматом менялось.
Можно и автоматом, можно и в строковых константах.
VD>Гы. Любимый аргумент любителей скриптов. "А у нас юнит-тесты есть".
Дело не в скриптах, а в том, что юнит-тесты много где могут пригодится, в том числе и в БД.
Здравствуйте, gandjustas!
G>Видимо про UI недопоняли друг друга. G>Разделяю вашу точку зрения.
Дико извиняюсь — без причины наехал на человека, когда вокруг столько кандидатов... упс
G>Если пытаться вытягивать кучу связанных сущнстей из БД, то это может превратиться в огромную портянку заджойненых данных. G>Передача сериализованных объектов бдет экономичнее.
Не дошло — вы про денормализацию? Бесполезно ведь для работы с данными, разве что только для отчётов...
Или вы про грабли с выборкой части данных? Если второе — то решается кучей способов. Как правило заводитсся view типа UserOrders, который внутри себя определяет какие из заказов доступны текущему пользователю, и пишутся хранимки, что жойнят view c нужными таблицами (допустим, orders и orderdetails) и отдают нужные данные.
С точки зрения клиента в базе вообще нет данных, кроме тех что он выгребает (на самом деле и тех нет по большей части — они живут в других базах).
S>>На выходе имеем мешанину из сущностей различных типов, причём отслеживать изменения в контексте невозможно. Кэш нельзя использовать для удобной выборки локальных данных, для валидации при изменениях и для биндинга. Зачем он нужен в десктоп-клиенте? G>.OfType ? G>Для биндинга и валидации одной сущности и кеш не нужен. Достаточно одного объекта. G>Для графа надо создавать отдельный viewmodel.
Ну собстно мы и пришли к одному и тому же выводу, только я его озвучиваю слегка провокационно
Здравствуйте, kenzo_u, Вы писали:
_>Давно я не встречал технических документов, которые были написаны хуже чем этот. Уже несколько лет читаю книги и литературу на английском, но этот текст заставил меня неслабо напрягаться и перечитывать предложения и абзацы по несколько раз.
Ничего, есть и более плохой вариант
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinix, Вы писали: S>0) почему база-то будет загибаться??? ей практически всё равно сколько данных отдавать, если они хорошо нормализованы и хороший index coverage. Скорее наоборот, куча мелких обращений обойдётся дороже. S>1) у нас всё ещё десктоп клиент, так? В память выгребаются только данные, нужные клиенту. От пары тысяч сущностей он загнётся?
Не понимаю, как вы собираетесь проверить глобальную уникальность по паре тысяч сущностей. Пожалуйста, поподробнее — это может быть переворот в управлении данными!
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Если коротко, там обсуждалась только нагрузка на одного клиента, где-то рядом ещё обсуждали проблему локальной валидации и возможность сделать её декларативно силами EF.
На глобальную валидацию никто вроде не замахивался.
Есть желание — напишу кучу других неправильных букв про то, чем хороши локальные проверки.
Здравствуйте, Sinix, Вы писали: S>Если коротко, там обсуждалась только нагрузка на одного клиента, где-то рядом ещё обсуждали проблему локальной валидации и возможность сделать её декларативно силами EF.
Брр. Я под локальной валидацией всегда понимал ту, которую можно выполнить, оставаясь в рамках валидируемого объекта.
Ну то есть бывает еще и стейтлесс локальная валидация — для которой достаточно анализа одного свойства, она особенно интересна потому, что ее легко проносить в GUI ("логин должен начинаться с буквы и содержать буквы, цифры, или подчеркивания").
Глобальной я считал валидацию, которая затрагивает недетерминированное количество объектов. И мне крайне интересно, каким образом можно ее сделать без обращения к базе и без подтягивания в кэш клиента полной копии базы.
S>На глобальную валидацию никто вроде не замахивался.
Уникальность — типичное требование глобальной валидации. Именно на нее был сделан четкий замах вот в этом
постинге, разве нет? Там вроде датасет обеспечивал ее бесплатно, на rbtree индексах, и в базу не бегал. Как так?
S>Есть желание — напишу кучу других неправильных букв про то, чем хороши локальные проверки.
Да конечно, нужно только прояснить термины.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinix, Вы писали:
G>>Если пытаться вытягивать кучу связанных сущнстей из БД, то это может превратиться в огромную портянку заджойненых данных. G>>Передача сериализованных объектов бдет экономичнее.
S>Не дошло — вы про денормализацию? Бесполезно ведь для работы с данными, разве что только для отчётов... S>Или вы про грабли с выборкой части данных? Если второе — то решается кучей способов. Как правило заводитсся view типа UserOrders, который внутри себя определяет какие из заказов доступны текущему пользователю, и пишутся хранимки, что жойнят view c нужными таблицами (допустим, orders и orderdetails) и отдают нужные данные. S>С точки зрения клиента в базе вообще нет данных, кроме тех что он выгребает (на самом деле и тех нет по большей части — они живут в других базах).
Не, все гораздо проще.
Вы смотрели что отдает SQL Server кода вы пишите красивый Linq\eSQL\HQL запрос с несколькими джоинами? Если этим данные замапить на граф объектов и сериализовать даже в XML, то xml будет весить гораздо меньше, чем то что отдает MS SQL.
Поэтому в сценариях где требуется сокращение нагрузки на сеть имеет смысл отдавать данные через сервисы в виде сериализованных объектов, а не использовать TDS или датасеты.
Кроме того при правильной готовке ADO.NET Data Services можно в несколько раз сократить затраты на передачу за счет клиентского кеширования протокола HTTP.
Здравствуйте, gandjustas!
G>Вы смотрели что отдает SQL Server кода вы пишите красивый Linq\eSQL\HQL запрос с несколькими джоинами? Если этим данные замапить на граф объектов и сериализовать даже в XML, то xml будет весить гораздо меньше, чем то что отдает MS SQL. G>Поэтому в сценариях где требуется сокращение нагрузки на сеть имеет смысл отдавать данные через сервисы в виде сериализованных объектов, а не использовать TDS или датасеты. G>Кроме того при правильной готовке ADO.NET Data Services можно в несколько раз сократить затраты на передачу за счет клиентского кеширования протокола HTTP.
О! Вона вы про что
При такой постановке вопроса полностью согласен. С друой стороны это проблемы кривых запросов, не sql server'a. Такое по возможности лучше решать на месте, а не заводить пайп из костылей каждый из которых решает проблемы предыдущего.
По терминам у нас реальная солянка. В одну кучу свалились 4 юз-кейса:
1) stateless валидация ака ограничения на одну сущность — решается примерно одинаково абсолютно везде — IDataErrorInfo+IEditableObject в руки и паехали.
2) Проверка локального графа объектов. Реализуется датасетами при помощи uniqueConstraints. EF — своя viewModel
3) Проверка при/перед сохранением. Решается примерно одинаково — событиями при получении ошибок от сервера.
4) Глобальная проверка на каждый чих. Решается примерно одинаково — никак
4 нереализуемо в общем случае — всё сводится к когерентности локальных кэшей и обнаружении ошибок в _ещё не сохранённых данных_. Обычно ограничиваются проверкой при сохранении, т.е. 3.
п2 полезен в сценариях, когда каждый пользователь работает в своей песочнице и по возможности не лезет к другим. Если же взаимодействие необходимо, оно оформляется в реальный воркфлоу, а не делается через побочные эффекты
По ссылке мы обсуждали сценарий 2, речь шла о partial disconnected apps и об ограничениях внутри контекста — полная цитата:
G>Смотрю сгенерированные EF классы — оповещения будут.
Это оповещения на изменение свойств элемента. Они хороши для биндинга к конкретной сущности. Попробуйте отследить добавление/удаление/изменение любой сущности — причём именно те, что будут отражены в базе. У ObjectContext только одно событие — SavingChanges. Вы конеш можете проводить валидацию внутри сущностей, но это во-первых намекает о жирной модели. Во-вторых, вы не сможете так проверять сложные ограничения, что требуют доступа ко всему контексту. Или хотя бы отследить тот факт, что сущность поменяла родителя
Кстати, попробуйте реализовать ограничение на уникальность любого поля. EDM позволяет определить только один Key. Даже элементарное требование несуществования двух сущностей с одинаковыми именами уже требует приседаний. Напомню — нарушение ограничений должно обнаруживаться при попытке изменения сущности, чтобы можно было его отловить и исправить на месте. Вы внимательней присмотритесь к EDM. Как средство описания модели данных она довольно убога.
Здравствуйте, gandjustas, Вы писали: G>Вы смотрели что отдает SQL Server кода вы пишите красивый Linq\eSQL\HQL запрос с несколькими джоинами? G>Если этим данные замапить на граф объектов и сериализовать даже в XML, то xml будет весить гораздо меньше, чем то что отдает MS SQL.
Всё очевидным образом зависит от того, какова доля джойнов, и какова доля проекций. А также размер "основной" таблички. Если вытаскивать данные постранично, ограничивая размер результата осмысленными значениями, то, я боюсь, тяжко придется XML.
Поясняю мысль: вот у нас, допустим, список заказов. Нет, даже пусть это будет список позиций заданной накладной — так интереснее.
Потому что каждая строчка — почти чистый набор FK. И в ней, по идее, client-side join должен рулить со страшной силой.
Ну, давайте посчитаем:
1. Граф объектов.
Строки:
{
OrderID: 16
ItemID: 16
ProductID: 16
Quantity: 4
Price: 4
}
Итого: 56 байт. * 100 (строк).
Cобсно, продукты:
{
ProductID: 16
Name: 64 (средняя длина)
CategoryID: 16
Description: 400
Image: 16000
}
Итого: 16496. * 100 (ясен хрен, что все позиции ссылаются на различные товары)
Внимание, вопрос: кто победит?
G>Поэтому в сценариях где требуется сокращение нагрузки на сеть имеет смысл отдавать данные через сервисы в виде сериализованных объектов, а не использовать TDS или датасеты.
Вопрос мне не кажется столь уж однозначным. В большом-большом количестве случаев тащить повторно приджойненный кусочек (например, город где живет клиент) для каждой строки несущественно дороже таскания FK на этот объект. И это даже если не считать то, что объекты в графе будут тащить с собой тонны мусора — см. Description и Image в товаре.
Поэтому далеко не все графы шибко выиграют от сериализации. G>Кроме того при правильной готовке ADO.NET Data Services можно в несколько раз сократить затраты на передачу за счет клиентского кеширования протокола HTTP.
А вот это — строго правда. Поэтому RESTful Services рулят просто как водитель маршрутки в пробке.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, Sinclair!
S>По терминам у нас реальная солянка. В одну кучу свалились 4 юз-кейса:
S>1) stateless валидация ака ограничения на одну сущность — решается примерно одинаково абсолютно везде — IDataErrorInfo+IEditableObject в руки и паехали. S>2) Проверка локального графа объектов. Реализуется датасетами при помощи uniqueConstraints. EF — своя viewModel
Я не понимаю, каков глубокий смысл проверять локальный граф объектов на уникальность.
S>4) Глобальная проверка на каждый чих. Решается примерно одинаково — никак
Прекрасно решается в асинхронной модели. Вон, гугл же успевает "глобально" проверять, нет ли поисковых запросов, похожих на то, что ты вводишь. Какие проблемы?
S>4 нереализуемо в общем случае — всё сводится к когерентности локальных кэшей и обнаружении ошибок в _ещё не сохранённых данных_.
Нереализуемо только в случае искусственного придумывания локальных кэшей. Все глобальные проверки делают только одно: проверяют "еще несохранённые" данные относительно "уже сохраненных".
Сумма транзакции проверяется на предмет превышения баланса; е-мейл проверяется на предмет уникальности; пароль проверяется на предмет совпадения с предыдущими семьюстами.
Никого не скребет, если ты открыл две формы, и в каждой из них набрал "списать 700р" при остатке в 1000. Им совершенно не нужно учитывать друг друга. Вот сделаешь одной сабмит — вторая потупит-потупит, да и выкинет ворнинг "ахтунг, приятель, деньги-то кончаются".
S>Обычно ограничиваются проверкой при сохранении, т.е. 3.
S>п2 полезен в сценариях, когда каждый пользователь работает в своей песочнице и по возможности не лезет к другим.
Непонятно. Если каждый пользователь работает в своей песочнице, то у вас нет общей базы и повода для конфликтов.
S>Если же взаимодействие необходимо, оно оформляется в реальный воркфлоу, а не делается через побочные эффекты
S>По ссылке мы обсуждали сценарий 2, речь шла о partial disconnected apps и об ограничениях внутри контекста — полная цитата:
Вот мне и непонятно — вы что, всеръез предлагаете пользователям в начале работы забирать к себе полную песочницу в виде датасета, а в конце ее записывать обратно?
Моей фантазии не хватает придумать приложение, где бы это работало мало-мальски эффективно.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, gandjustas, Вы писали: G>>Вы смотрели что отдает SQL Server кода вы пишите красивый Linq\eSQL\HQL запрос с несколькими джоинами? G>>Если этим данные замапить на граф объектов и сериализовать даже в XML, то xml будет весить гораздо меньше, чем то что отдает MS SQL. S>Всё очевидным образом зависит от того, какова доля джойнов, и какова доля проекций. А также размер "основной" таблички. Если вытаскивать данные постранично, ограничивая размер результата осмысленными значениями, то, я боюсь, тяжко придется XML.
Видимо я слишком категорично написал это утверждение.
S>Поясняю мысль: вот у нас, допустим, список заказов. Нет, даже пусть это будет список позиций заданной накладной — так интереснее. S>Потому что каждая строчка — почти чистый набор FK. И в ней, по идее, client-side join должен рулить со страшной силой. S>Ну, давайте посчитаем: S>1. Граф объектов. S>
S>Внимание, вопрос: кто победит?
Вообще говоря немного нечестное сравнение. В этом случае по заджойненным данным не получится восстановить граф объектов.
Да и не всегда джойниться будут разные строки.
G>>Поэтому в сценариях где требуется сокращение нагрузки на сеть имеет смысл отдавать данные через сервисы в виде сериализованных объектов, а не использовать TDS или датасеты. S>Вопрос мне не кажется столь уж однозначным. В большом-большом количестве случаев тащить повторно приджойненный кусочек (например, город где живет клиент) для каждой строки несущественно дороже таскания FK на этот объект. И это даже если не считать то, что объекты в графе будут тащить с собой тонны мусора — см. Description и Image в товаре.
Конечно правильные джоины и проекции будут рулить в любом случае. Только их еще писать надо.
В тоже время ADO.NET Data Services позволяют вытаскивать на клиента объекты данных при этом меньше забивая сеть, чем TDS.
Но это при тупом написании.
Здравствуйте, gandjustas, Вы писали: G>Вообще говоря немного нечестное сравнение. В этом случае по заджойненным данным не получится восстановить граф объектов.
Честное. Нахрена козе баян... тьфу, клиенту граф объектов? Ему нужна некоторая ViewModel, которую можно отобразить. В ней граф объектов — это излишество.
Граф объектов в ОРМ появился оттого, что уж очень дорого описывать типы "по месту". Поэтому ОРМщики привыкают обходиться тем, что есть — собирать View вручную. Упрощение этого процесса
G>Да и не всегда джойниться будут разные строки.
Не всегда. Я про одинаковые строки тоже написал — во многих случаях мы имеем star-join, где от каждого FK нам необходимо и достаточно иметь по одному полю.
В общем, для подбора убедительного примера с победой сериализации графв нужно еще постараться
G>Конечно правильные джоины и проекции будут рулить в любом случае. Только их еще писать надо.
А граф объектов что, волшебной силой на клиента прилетит и во View отобразится?
G>В тоже время ADO.NET Data Services позволяют вытаскивать на клиента объекты данных при этом меньше забивая сеть, чем TDS. G>Но это при тупом написании.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
G>>Да и не всегда джойниться будут разные строки. S>Не всегда. Я про одинаковые строки тоже написал — во многих случаях мы имеем star-join, где от каждого FK нам необходимо и достаточно иметь по одному полю. S>В общем, для подбора убедительного примера с победой сериализации графв нужно еще постараться
Если посмотреть реальные проекты, написанные среднестатистическим программистом, то и стараться особо не придется.
То что с нормальными выборками и проекциями можно сделать гораздо лучше я даже не сомневаюсь (и сам так делаю).
G>>Конечно правильные джоины и проекции будут рулить в любом случае. Только их еще писать надо. S>А граф объектов что, волшебной силой на клиента прилетит и во View отобразится?
Ага.
Я на демонстрации возможнойстей SL такое покаывал. Буквально 10 минут дела.
Здравствуйте, IB, Вы писали:
VD>> Статья 2004 года, а в 2008, как я понимаю как раз в области планов были серьезные изменения. IB>Серьезных не было. Там планомерные улучшения с 2000-й версии.
У меня другая информация. Кое что после выхода 2008-го устарело.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, IB, Вы писали:
IB>Здравствуйте, VladD2, Вы писали:
IB>Нет, у меня реакция — "есть но непонятно зачем". На практике такое пожалуй только для поддержки легаси кода нужно, ну или какая-нибудь экзотика...
Гегаси?
Что уже есть устаревшие системы с триггерами на дотнете?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, IB, Вы писали:
VD>>Гы. Любимый аргумент любителей скриптов. "А у нас юнит-тесты есть". IB>Дело не в скриптах, а в том, что юнит-тесты много где могут пригодится, в том числе и в БД.
Это понятно. Только они сами по себе не аргумент. Почти у всех есть юнит-тесты. Но это не делает не нужным комнтроль компилятора или грамотное проектирования. Это еще один вид защиты и средство отладки. Не более, и не менее того.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>У меня другая информация. Кое что после выхода 2008-го устарело.
Сейчас еще раз бегло просмотрел документацию по 2008-у — ничего супер нового. Основные изменения были в 2005, когда добавили ручек побольше для управления кешированием.
Здравствуйте, VladD2, Вы писали:
VD>Что уже есть устаревшие системы с триггерами на дотнете?
нет, есть клиент-серверные системы, с голой бд наружу, которым надо серверную логику прикрутить.
Здравствуйте, IB, Вы писали:
VD>>У меня другая информация. Кое что после выхода 2008-го устарело. IB>Сейчас еще раз бегло просмотрел документацию по 2008-у — ничего супер нового. Основные изменения были в 2005, когда добавили ручек побольше для управления кешированием.
Ты бы еще форум бегло почитал по этому поводу.
Там не много изменили, но реакция изменилась координально. Например, сброс кэша в 2005 все равно не приводил к нужному результату иногда, а в 2008 это изменили. Подробностей не помню, но точно помню, что кое-что поменялось.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, IB, Вы писали:
VD>>Что уже есть устаревшие системы с триггерами на дотнете? IB>нет, есть клиент-серверные системы, с голой бд наружу, которым надо серверную логику прикрутить.
Сдается мне триггеры на полноценном языке могли бы пригодиться многим.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
VD>Например, сброс кэша в 2005 все равно не приводил к нужному результату иногда, а в 2008 это изменили.
Сброс кеша всегда приводил к нужному результату — сбросу кеша. Это еще в 7.0 точно работало.. =)
VD>Подробностей не помню, но точно помню, что кое-что поменялось.
Рабинович насвистел? =)
Здравствуйте, VladD2, Вы писали:
VD>Сдается мне триггеры на полноценном языке могли бы пригодиться многим.
А мне сдается что нет. Ни триггеры, ни хранимки. Всю серьезную логику не связанную непосредственно с SQL-ем, все равно проще удобнее и правильнее делать в прикладном коде.
Ндя... По ходу читать с середины дискуссии вредно вообще.
Была цепочка:
-EF малоприменимо в десктоп-приложениях/
-почему?
-например, тяжело писать partial-disconnected apps-а/
-что такого в этих partial-disconnected? Вы неправильно готовите EF!
И панеслась. Если посмотреть на всю нашу ветку,видно что обсуждалась именно неприменимость EF как локального кэша данных из каропки. Из контекста одного сообщения это совершенно неочевидно.
Тем не менее распишу свою точку зрения.
Partial disconnected великолепнейше работает, когда есть куча рабочих мест, и каждый пользователь системы работает со своей порцией данных. Локальный кэш даёт возможность находить ошибки по мере редактирования, не пиная при этом сервер. То есть не кэш заводится ради проверок, а, наоборот, используется для валидации, которую можно провести локально. Локальные проверки ни в коем случае не подменяют собой проверок при сохранении. При такой расстановке акцентов пойдёт?
S>>4) Глобальная проверка на каждый чих. Решается примерно одинаково — никак S>Прекрасно решается в асинхронной модели. Вон, гугл же успевает "глобально" проверять, нет ли поисковых запросов, похожих на то, что ты вводишь. Какие проблемы?
Мы всё ещё говорим о проверках во время редактирования?
Подход гугла применим при редактировании примитивов. Проверка, что совместное редактирование сложного графа объектов не нарушает ограничений — безумно тяжкая вешь. Проще уж либо сразу блокировку на граф навесить, либо решать проблемы при внесении изменений.
Даже примитивное ограничение "сумма полей a и b не должна превышать 10" не подлежит моментальной глобальной валидации. Точнее, проверить-то можно, но это не даёт никаких гарантий, что при сохранении это ограничение не будет нарушено новыми изменениями. Зато сервер будет перегружен кучами мелких запросов.
Чтобы _гарантированно_ проверить, что одновременное редактирование не приведёт базу в рассогласованное состояние, нам надо знать обо всех изменениях, ещё не внесённых в базу. Дальше нам надо каким-то образом сэмулировать внесение всех этих изменений и проверить все ограничения. Не слишком большая работа для организация "умного" подсвечивания ошибок?
S>Сумма транзакции проверяется на предмет превышения баланса; е-мейл проверяется на предмет уникальности; пароль проверяется на предмет совпадения с предыдущими семьюстами. S>Никого не скребет, если ты открыл две формы, и в каждой из них набрал "списать 700р" при остатке в 1000. Им совершенно не нужно учитывать друг друга. Вот сделаешь одной сабмит — вторая потупит-потупит, да и выкинет ворнинг "ахтунг, приятель, деньги-то кончаются".
Здесь вы говорите о сценарии 3 — проверке при сохранении. Как уже писал — она реально необходима. Тем не менее, каждая ошибка, возникающая при такой проверке — неявный признак косяка в проектировании UI. Чтобы избежать подобных проблем, можно например ввести проверку, что товарищ уже не залогинился где-либо ещё.
S>>п2 полезен в сценариях, когда каждый пользователь работает в своей песочнице и по возможности не лезет к другим. S>Непонятно. Если каждый пользователь работает в своей песочнице, то у вас нет общей базы и повода для конфликтов.
... S>Вот мне и непонятно — вы что, всеръез предлагаете пользователям в начале работы забирать к себе полную песочницу в виде датасета, а в конце ее записывать обратно? S>Моей фантазии не хватает придумать приложение, где бы это работало мало-мальски эффективно.
Ух... как всё вверх ногами-то перевернульось!
Попробуем ещё раз. У нас есть некоторая база данных. Есть несколько пользователей, которые одновременно вносят изменения. Диапазоны доступных данных у пользователей не будут одинаковыми — например, из-за ограничений доступа.
При одновременном редактировании одних и тех же сущностей неизбежны конфликты. Поэтому работа пользователей организуется таким образом, чтобы один товарищ не мешал другому — это чисто административные меры. Отсюда и берутся "почти непересекающиеся" песочницы.
Тем не менее, при редактировании своих данных каждый товарищ может внести сложные ошибки, которые можно обнаружить, только проверив весь граф объектов. Если граф уже есть на клиенте (а часть его скорее всего там есть, раз уж мы его изменяем), то по возможности такие ошибки надо проверять на месте.
На всякий. Речь идёт не о вытягивании всей базы на клиента, а об организации работы так, чтобы каждый пользователь мог работать с небольшим сегментом данных и не заботиться о том, что он кому-то что-то поломает.
Если мои неправильные буквы вызовут вопросы и на этот раз — придётся признать что я совершенно не умею выражать свои мысли и свернуть дискуссию
Здравствуйте, Sinix, Вы писали:
S>Partial disconnected великолепнейше работает, когда есть куча рабочих мест, и каждый пользователь системы работает со своей порцией данных. Локальный кэш даёт возможность находить ошибки по мере редактирования, не пиная при этом сервер. То есть не кэш заводится ради проверок, а, наоборот, используется для валидации, которую можно провести локально. Локальные проверки ни в коем случае не подменяют собой проверок при сохранении. При такой расстановке акцентов пойдёт?
Я продолжаю непонимать. Слишком абстрактно написано. Какие именно проверки "можно провести локально"? Неоднократно звучал пример про уникальность. Я в очередной раз прошу объяснить, каким образом это собирается работать.
Поясню — по-видимому, мои вопросы как-то не так сформулированы:
1. Вот у нас есть N объектов, каждый из которых должен быть уникален по какому-то признаку.
2. Вот у нас есть локальный кэш, в котором лежат K объектов
3. И вот пользователь изменяет один из этих К объектов.
Какой смысл в локальной проверке на уникальность? Как вы обеспечите достаточно низкую вероятность того, что дубликат есть среди N-K объектов?
S>Мы всё ещё говорим о проверках во время редактирования?
Да. S>Подход гугла применим при редактировании примитивов. Проверка, что совместное редактирование сложного графа объектов не нарушает ограничений — безумно тяжкая вешь. Проще уж либо сразу блокировку на граф навесить, либо решать проблемы при внесении изменений.
Я не очень понимаю, что такое "сложный граф объектов". Какого рода ограничения вы хотите проверять? В RDBMS приняты всего четыре типа ограничений:
1. Ограничения на скалярные вводимые значения — малоинтересны нам
2. Ограничения уровня строки
3. Ограничения foreign key
4. Ограничения uniqueness
Я могу придумать еще много видов, но в большинстве случаев они сведутся к развитию 3 и 4. Ну, например, foreign key будет проверять не наличие значения в целой таблице, а в каком-то подмножестве.
S>Даже примитивное ограничение "сумма полей a и b не должна превышать 10" не подлежит моментальной глобальной валидации.
А зачем тут глобальная валидация? Мы же это обсуждали. Почему в ответ на вопрос про ограничения типа 3 и типа 4 приводится пример типа 2? S>Точнее, проверить-то можно, но это не даёт никаких гарантий, что при сохранении это ограничение не будет нарушено новыми изменениями.
Правильно. Это совершенно корректная точка зрения — до коммита транзакции вообще никаких гарантий дать нельзя. Такова жестокая природа.
Но я совершенно согласен с тем, что это не повод вообще не выполнять проверок в процессе ввода. Надо делать так, как удобно пользователю.
S>Зато сервер будет перегружен кучами мелких запросов.
Да, это плохо, но я в упор не вижу, каким образом можно провести валидацию без обращения к серверу. Я не против нее — только объясните уже, какой магией это заработает!
S>Чтобы _гарантированно_ проверить, что одновременное редактирование не приведёт базу в рассогласованное состояние, нам надо знать обо всех изменениях, ещё не внесённых в базу.
НЕТ!!!!
Я же написал русским по белому: каждое изменение проверяется в предположении, что оно — единственное.
S> Дальше нам надо каким-то образом сэмулировать внесение всех этих изменений и проверить все ограничения. Не слишком большая работа для организация "умного" подсвечивания ошибок?
Не нужно ничего эмулировать. Приведите пример, где бы это потребовалось.
S>Здесь вы говорите о сценарии 3 — проверке при сохранении.
Нет, я говорю именно о проверке до сохранения. Вот я набрал в форме "700р". Клиент сбегал проверил — баланс на счету достаточный, можно нажимать Ok. Но я не нажимаю. Значит, клиент будет вынужден иногда бегать на сервер за обновлениями. Почему? Да потому, что могло быть наоборот — я набрал "2000р". Да, я в курсе, что в момент открытия формы там было 1000. Но я знаю, что с минуты на минуту мне на счет положат еще 5000р. Клиент не должен запрещать мне попытку провести деньги — он может быть не в курсе, что там происходит на другом конце. S>Как уже писал — она реально необходима. Тем не менее, каждая ошибка, возникающая при такой проверке — неявный признак косяка в проектировании UI.
Какой-то он очень неявный, этот признак. Я не верю в то, что возможно спроектировать UI с гарантией выполнения таких требований. Он бы потребовал удержания транзакции на уровне serializable с самого начала перехода в режим редактирования и до самого коммита. Технически это возможно, но будет очень-очень хреново масштабироваться.
Поэтому на мой взгляд имеет смысл несколько снизить требования к UI. И я полагал, что именно этот вариант мы и обсуждаем — клиент старается сделать как можно больше, но ничего не гарантирует до сохранения.
S>Чтобы избежать подобных проблем, можно например ввести проверку, что товарищ уже не залогинился где-либо ещё.
Зачем? Кому нужны эти ограничения?
S>Попробуем ещё раз. У нас есть некоторая база данных. Есть несколько пользователей, которые одновременно вносят изменения. Диапазоны доступных данных у пользователей не будут одинаковыми — например, из-за ограничений доступа.
Прекрасно. S>При одновременном редактировании одних и тех же сущностей неизбежны конфликты. Поэтому работа пользователей организуется таким образом, чтобы один товарищ не мешал другому — это чисто административные меры. Отсюда и берутся "почти непересекающиеся" песочницы.
Но ведь ограничения-то выходят за пределы песочниц! Если мы говорим об уникальности в пределах песочницы — так и говорите. Но у меня сложилось впечатление, что речь идет о глобальной уникальности.
S>Тем не менее, при редактировании своих данных каждый товарищ может внести сложные ошибки, которые можно обнаружить, только проверив весь граф объектов. Если граф уже есть на клиенте (а часть его скорее всего там есть, раз уж мы его изменяем), то по возможности такие ошибки надо проверять на месте.
Вот мне и непонятно, каким образом вы выполняете "проверку всего графа", когда на клиенте скорее всего его часть.
S>На всякий. Речь идёт не о вытягивании всей базы на клиента, а об организации работы так, чтобы каждый пользователь мог работать с небольшим сегментом данных и не заботиться о том, что он кому-то что-то поломает.
Это понятно. Намерения ваши были ясны еще с первого постинга. Я просто не понимаю, как вы собираетесь их выполнять.
S>Если мои неправильные буквы вызовут вопросы и на этот раз — придётся признать что я совершенно не умею выражать свои мысли и свернуть дискуссию
Не нужно выражать мысли. Вы просто на вопросы ответьте.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, Sinclair.
S>Ндя... По ходу читать с середины дискуссии вредно вообще.
S>Была цепочка: S>-EF малоприменимо в десктоп-приложениях/ S>-почему? S>-например, тяжело писать partial-disconnected apps-а/ S>-что такого в этих partial-disconnected? Вы неправильно готовите EF!
Я разве говорил о partial-disconnected apps?
Я говорил о применимости EF в connected n-tier приложениях.
Для partial-disconnected есть sync services и локальная БД.
По ходу мы говорим вообще о разных вещах: вы — о верификации, т.е. гарантированной проверке на нерассогласованность.
Я — о возможном обнаружении ошибок, единственная цель этого обнаружения — выдать варнинг на месте и помочь пользователю их исправить.
Кстати под юз-кейзом 4 у нас также оказались два варианта — я имел в виду именно глобальную верификацию, которая как раз не нужна и не осуществима. Сорри
Верификация требует наличия соединения с сервером и гарантирует корректность только если проверка и изменение являются частью одной транзакции, или, другими словами, проверка — часть процесса внесения изменений. Это абсолютно очевидно, всё что ниже я пишу только для того, чтобы синхронизировать точки зрения.
Проверка силами СУБД без внесения изменений возможна для примитивных сценариев типа "а нет ли у нас уже такого имени?" — объём передаваемых данных мизерен. Если объём накопленных изменений на клиенте большой — а это довольно типичный сценарий, то каждое новое действие пользователя для проверки требует передачи всех изменённых данных. Конеш, можно оптимизировать, строя граф сущностей, которых затрагивает новое изменение и передавать для проверки только их, или проверяя только элементарные сценарии. Впрочем, даже для элементарных проверок могут возникать забавные грабли — типа внесения в контекст двух сущностей с одинаковыми именами.
Опять-таки, одновременная работа множества клиентов порождает нехилые волны проверок, которые выносят кэш СУБД, вытесняя страницы, что используются для редких, но ресурсоёмких операций.
Часть из проверок можно производить локально, если сответствующие данные есть на клиенте. Эти проверки разумеется не дадут гарантированного результата, это не верификация — боже упаси, а только предварительное прощупывание на предмет возможных ошибок. С другой стороны, проверка данных в СУБД без внесения изменений тоже не даёт гарантий корректности данных, так что здесь оба способа предварительной проверки равноправны.
А дальше начинается обычная оценка — какие проверки выгодней оосуществлять локально, а какие придётся делегировать субд. Для десктоп-клиентов число проверок, которые можно проводить локально обычно очень велика. Ещё раз: мы говорим не о 100%-й уверенности "у тебя здесь ошибка" а о предупреждении "при сохранении будут внесены неверные данные".
Самый тупой пример — папки + документы. При переходе пользователя в папку в кэше оказываются все документы (естественно, метаданные, а не содержимое документов). Зная этот факт, можно поставить ограничение на уникальность {id_папки; имя документа} и наслаждаться жизнью. Тема о уникальности была поднята как самый очевидный пример локальных проверок. Оказалось — не такой очевидный.
Главаная грабля в написании partial disconnected софта — соблюдать баланс, чтобы с одной стороны клиент не захлебнулся от жадности, а с другой — не нагружать по возможности сервер. При должной степени аккуратности получается дешёвое и масштабируемое решение.
Естественно нет никакого правила большого пальца типа "все FK проверяются локально, любое UQ требует пинка серверу".
Тем не менее dal должен предоставлять способ валидации изменений вне зависимости от способа, которым эта препроверка будет осуществляться. Если dal умеет описывать часть локальных проверок декларативно — то это вообще замечательно
К сожалению, EF прям таки заставляет или отказываться от локальных проверок, или заводить свой viewmodel, который в значительной степени будет дублировать функционал датасетов.
Сорри, не имел вас в виду — вопрос про partial disconnected мы начали обсуждать с cyberax.
SyncServices предназначены для offline clients|occansionally connected clients. Это слегка другой сценарий: http://msdn.microsoft.com/en-us/sync/bb887608.aspx
Для эффективной работы SyncServices требуют хоть-какой нибудь change tracking и (для провайдера искаропки) прямой доступ к таблицам. Для partial disconnected типичный режим работы "коннектимся-заливаем небольшой объём данных-рабьотаем-синхронизация-работаем..." И здесь local db получается излишним оверкиллом.
Здравствуйте, Sinix, Вы писали:
S>По ходу мы говорим вообще о разных вещах:
Да. И если вы не начнете отвечать на вопросы, ситуация никак не изменится. Не нужно пытаться угадать, о чем я толкую.
Просто отвечайте на вопросы, и задавайте свои, если что-то непонятно.
Иначе у нас получается два несвязанных монолога.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, gandjustas!
S>Сорри, не имел вас в виду — вопрос про partial disconnected мы начали обсуждать с cyberax. S>SyncServices предназначены для offline clients|occansionally connected clients. Это слегка другой сценарий: S>http://msdn.microsoft.com/en-us/sync/bb887608.aspx
Это точно такой же сценарий, не вижу разницы.
S>Для эффективной работы SyncServices требуют хоть-какой нибудь change tracking и (для провайдера искаропки) прямой доступ к таблицам.
Можно работать через сервисы, а change-tracking дается бесплатно.
Работает это все гораздо лучше, чем change-tracking датасетов.
S>Для partial disconnected типичный режим работы "коннектимся-заливаем небольшой объём данных-рабьотаем-синхронизация-работаем..." И здесь local db получается излишним оверкиллом.
не вижу почему будет оверкиллом?
Персистентность локальной копии данных + возможность обращаться к ней с помощью SQL (следовательно тот же EF или Linq2SQL) очень даже полезна.
Извиняюсь за временное отсутствие наличия. Поскольку попытки изложить свои мысли связно и одним постом явно не находят понимания — вернёмся к цитатам на цитаты
S>Я не понимаю, каков глубокий смысл проверять локальный граф объектов на уникальность.
Проверка силами СУБД без внесения изменений возможна для примитивных сценариев типа "а нет ли у нас уже такого имени?" — объём передаваемых данных мизерен. Если объём накопленных изменений на клиенте большой — а это довольно типичный сценарий, то каждое новое действие пользователя для проверки требует передачи всех изменённых данных. Конеш, можно оптимизировать, строя граф сущностей, которых затрагивает новое изменение и передавать для проверки только их, или проверяя только элементарные сценарии. Впрочем, даже для элементарных проверок могут возникать забавные грабли — типа внесения в контекст двух сущностей с одинаковыми именами.
Опять-таки, одновременная работа множества клиентов порождает нехилые волны проверок, которые выносят кэш СУБД, вытесняя страницы, что используются для редких, но ресурсоёмких операций.
Часть из проверок можно производить локально, если сответствующие данные есть на клиенте. Эти проверки разумеется не дадут гарантированного результата, это не верификация — боже упаси, а только предварительное прощупывание на предмет возможных ошибок. С другой стороны, проверка данных в СУБД без внесения изменений тоже не даёт гарантий корректности данных, так что здесь оба способа предварительной проверки равноправны.
S>Прекрасно решается в асинхронной модели. Вон, гугл же успевает "глобально" проверять, нет ли поисковых запросов, похожих на то, что ты вводишь. Какие проблемы?
1) Валидация с учётом всех невнесённых изменений на практике неосуществима (вы этого конеш не утверждали, я об этом писал — бред о когерентности кэшей именно к этому и относился)
2) Примитивные проверки работают прекрасно, но плохо масштабируются из-за выноса кэша СУБД. Сложные непрактичны из-за резкого роста трафика — приходится строить и передавать граф изменённых сущностей.
S>Нереализуемо только в случае искусственного придумывания локальных кэшей. Все глобальные проверки делают только одно: проверяют "еще несохранённые" данные относительно "уже сохраненных".
Вроде никто не говорил о том, что локальные проверки отменяют или подменяют глобальные. Они их просто дополняют, а при аккуратном подходе хорошо снижают нагрузку на сервер. Ничего большего я и не утверждал вроде, нет?
S>Непонятно. Если каждый пользователь работает в своей песочнице, то у вас нет общей базы и повода для конфликтов.
Нихт-нихт. Речь шла о том, что можно организовать работу пользователей с данными таким образом, что для каждого из них в базе нет никаких данных кроме тех, с которыми они работают. Для этого нужно как можно больше конфликтов предупреждать локально. Здесь локальные проверки и рулят.
S>Я продолжаю непонимать. Слишком абстрактно написано. Какие именно проверки "можно провести локально"? Неоднократно звучал пример про уникальность. Я в очередной раз прошу объяснить, каким образом это собирается работать.
Работать будет в двух сценариях:
1. Если известно, что данных в кэше всегда будет достаточно для проведения проверки. Пример про уникальность по составному ключу (имена документов в папке) приводился выше.
2. Если объём изменённых данных будет достаточно большим — массовые вставки или сеанс редактирования сложного графа объхектов.
S>Я не очень понимаю, что такое "сложный граф объектов". Какого рода ограничения вы хотите проверять? В RDBMS приняты всего четыре типа ограничений:
... S>Я могу придумать еще много видов, но в большинстве случаев они сведутся к развитию 3 и 4. Ну, например, foreign key будет проверять не наличие значения в целой таблице, а в каком-то подмножестве.
Речь шла о комплексных ограничениях — когда проверки при изменении одной сущности затрагивают ряд других сущностей. (возможно, даже не напрямую). Самая нетривиальная штука что мне приходилось решать — разруливание возможных циклов при обновлениях (пример условный, на практике было забавней)
Дано: в некоторй папке живут подпапки a,b, имена подпапок должны различаться.
Сначала a перенесли в b, затем создали новую папку с именем a и перенесли старую a в новую:
a -> -> a (new) -> a (new)
b b b |-a (old)
|-a |-a (old) b
В каждый отдельный момент граф находится в валидном состоянии. Теперь попробуйте внести изменения в базу данных, если change tracking хранит только 2 состояния: старое и новое. На практике всё было куда забавнее — циклы обновлений появлялись регулярно, захватывали десятки разнотипных сущностей и по требованиям должны были обнаруживаться немедленно.
Даже если бы этого требования не было, самое простое решение "записывать изменения" и "проигрывать их на сервере" не прошло бы — в промежуточных состояниях данные нарушали уже ограничения СУБД. Там было ещё много весёлых моментов. Например, составной частью процесса был импорт из зашифрованных файлов экселя. Единственный способ выгрести данные из такого файла по odbc — сначала открыть его в самом экселе и только после этого коннектиться. Вот только сам процесс экселя оставался висеть в памяти даже после закрытия окошка, а если его прибить — выдавал диалоговое окошко при следующем открытом файле и останавливал нафиг импорт (который работать по идее должен был автоматически). COM interop не проходил по каким-то полурелигиозным причинам — я тогда плюнул и не стал спорить.
И подобные ситуации — не экзотика, а нормальные побочные эффекты автоматизации уже сложившегося workflow. Так что локальные проверки бывают ой как нужны.
S>А зачем тут глобальная валидация? Мы же это обсуждали. Почему в ответ на вопрос про ограничения типа 3 и типа 4 приводится пример типа 2?
Уже писалось — под глобальной валидацией я наивно понимал проверку с учётом всех невнесённых изменений.
S>Нет, я говорю именно о проверке до сохранения. Вот я набрал в форме "700р". Клиент сбегал проверил — баланс на счету достаточный, можно нажимать Ok. Но я не нажимаю. Значит, клиент будет вынужден иногда бегать на сервер за обновлениями. Почему? Да потому, что могло быть наоборот — я набрал "2000р". Да, я в курсе, что в момент открытия формы там было 1000. Но я знаю, что с минуты на минуту мне на счет положат еще 5000р. Клиент не должен запрещать мне попытку провести деньги — он может быть не в курсе, что там происходит на другом конце.
Варнинг он хоть должен выдать-то? Ещё раз: локальные ограничения нужны в первую очередь для обнаружения и исправления возможных ошибок ввода — чтобы пользователю не пришлось откручивать назад стек и вспоминать что именно вызвало ошибку при сохранении.
S>Какой-то он очень неявный, этот признак. Я не верю в то, что возможно спроектировать UI с гарантией выполнения таких требований. Он бы потребовал удержания транзакции на уровне serializable с самого начала перехода в режим редактирования и до самого коммита. Технически это возможно, но будет очень-очень хреново масштабироваться. S>Поэтому на мой взгляд имеет смысл несколько снизить требования к UI. И я полагал, что именно этот вариант мы и обсуждаем — клиент старается сделать как можно больше, но ничего не гарантирует до сохранения. S>>Чтобы избежать подобных проблем, можно например ввести проверку, что товарищ уже не залогинился где-либо ещё. S>Зачем? Кому нужны эти ограничения?
Дык вроде никто и не замахивался на /*завоевание галактики*/ написание сверхнадёжного клиента — речь шла именно о предотвращении ошибок пользователя.
И с этой точки зрения запрет на одновременную работу нескольких товарищей под одним пользователем — довольно разумная вешь. Особенно если задачи, выполняемые пользователями распарралеливаются так, чтобы конфликты при редактировании возникали как можно реже. Ну и не стоит понимать запрет буквально — достаточно проверки с предупреждением.
S>>При одновременном редактировании одних и тех же сущностей неизбежны конфликты. Поэтому работа пользователей организуется таким образом, чтобы один товарищ не мешал другому — это чисто административные меры. Отсюда и берутся "почти непересекающиеся" песочницы. S>Но ведь ограничения-то выходят за пределы песочниц! Если мы говорим об уникальности в пределах песочницы — так и говорите. Но у меня сложилось впечатление, что речь идет о глобальной уникальности. S>>Тем не менее, при редактировании своих данных каждый товарищ может внести сложные ошибки, которые можно обнаружить, только проверив весь граф объектов. Если граф уже есть на клиенте (а часть его скорее всего там есть, раз уж мы его изменяем), то по возможности такие ошибки надо проверять на месте. S>Вот мне и непонятно, каким образом вы выполняете "проверку всего графа", когда на клиенте скорее всего его часть.
S>>На всякий. Речь идёт не о вытягивании всей базы на клиента, а об организации работы так, чтобы каждый пользователь мог работать с небольшим сегментом данных и не заботиться о том, что он кому-то что-то поломает. S>Это понятно. Намерения ваши были ясны еще с первого постинга. Я просто не понимаю, как вы собираетесь их выполнять.
Часть из проверок можно производить локально, если сответствующие данные есть на клиенте. Эти проверки разумеется не дадут гарантированного результата, это не верификация — боже упаси, а только предварительное прощупывание на предмет возможных ошибок. С другой стороны, проверка данных в СУБД без внесения изменений тоже не даёт гарантий корректности данных, так что здесь оба способа предварительной проверки равноправны.
А дальше начинается обычная оценка — какие проверки выгодней оосуществлять локально, а какие придётся делегировать субд. Для десктоп-клиентов число проверок, которые можно проводить локально обычно очень велика. Ещё раз: мы говорим не о 100%-й уверенности "у тебя здесь ошибка" а о предупреждении "при сохранении будут внесены неверные данные".
...
Главаная грабля в написании partial disconnected софта — соблюдать баланс, чтобы с одной стороны клиент не захлебнулся от жадности, а с другой — не нагружать по возможности сервер. При должной степени аккуратности получается дешёвое и масштабируемое решение.
Естественно нет никакого правила большого пальца типа "все FK проверяются локально, любое UQ требует пинка серверу".
Тем не менее dal должен предоставлять способ валидации изменений вне зависимости от способа, которым эта препроверка будет осуществляться. Если dal умеет описывать часть локальных проверок декларативно — то это вообще замечательно
Если на что-то не ответил — извиняйте. Поскольку размер постов с взаимными разъяснениями потихоньку подбирается к бесконечности, а постов по теме — к нулю, предлагаю закрыть тему.
Здравствуйте, gandjustas.
S>>Сорри, не имел вас в виду — вопрос про partial disconnected мы начали обсуждать с cyberax. S>>SyncServices предназначены для offline clients|occansionally connected clients. Это слегка другой сценарий: S>>http://msdn.microsoft.com/en-us/sync/bb887608.aspx G>Это точно такой же сценарий, не вижу разницы.
Тем не менее разница есть: offline clients предполагают, что клиент способен самостоятельно жить в офлайне и что эта жизнь имеет какой-никакой смысл. Главный критерий здесь мобильность.
А partial-disconnected apps это всего лишь способ снизить нагрузку на сеть/сервер и заодно реализовать сценарии, что трудно реализовать без локального кэша. Здесь данные постоянно находятся в памяти — in-memory db просто не нужна.
S>>Для эффективной работы SyncServices требуют хоть-какой нибудь change tracking и (для провайдера искаропки) прямой доступ к таблицам. G>Можно работать через сервисы, а change-tracking дается бесплатно. G>Работает это все гораздо лучше, чем change-tracking датасетов.
Я как-то не понимаю, как чанжтракинг становится бесплатным. И каким боком он будет лучше датасетов. Разжуйте плиз.
Ну вот смотрите:
Вариант 1: Используем датасеты.
Деплоймент клиента: всё искаропки.
Особые требования к СУБД: никаких.
Передача данных: Данные заливаются с базы данных как tds, обратно — изменённые данные как параметры RPC (если хранимые процедуры, если ad-hoc sql — +текст команды).
Вариант 2: EF + SQL CE + ADO.NET DataServices или SSDS (если их таки выпустят). Вы ведь это имели в виду
Деплоймент клиента: помимо фреймворка ставится sql ce — xcopy install уже не катит. // пустая придирка — решается install policies.
Особые требования к СУБД:
1) Наличие rowversion столбца.
2) прямой доступ к таблицам или к представлениям.
Передача данных:
субд — сервисы: tds;
сервисы — sql ce: xml по rest -> ??? -> сохранение в sql ce;
sql ce — клиент: ef -> shared memory.
А как вы собираетесь подружить SyncServices и DataServices? В мсдн нет ни слова по поводу их скрещивания. Первые используют датасеты для передачи данных между sql ce и провайдером, вторые — ef + wcf. Писать свой провайдер имхо получится слишком дорого. Если есть наводки — поделитесь.
S>>Для partial disconnected типичный режим работы "коннектимся-заливаем небольшой объём данных-рабьотаем-синхронизация-работаем..." И здесь local db получается излишним оверкиллом. G>не вижу почему будет оверкиллом? G>Персистентность локальной копии данных + возможность обращаться к ней с помощью SQL (следовательно тот же EF или Linq2SQL) очень даже полезна.
Про оверкилл написал выше. Персистентность для partial connected нужна разве что для бэкапа на случай пропажи питания/выгрузки данных на случай нехватки памяти. Для датасетов есть Linq2DataSets.
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, gandjustas.
S>>>Сорри, не имел вас в виду — вопрос про partial disconnected мы начали обсуждать с cyberax. S>>>SyncServices предназначены для offline clients|occansionally connected clients. Это слегка другой сценарий: S>>>http://msdn.microsoft.com/en-us/sync/bb887608.aspx G>>Это точно такой же сценарий, не вижу разницы.
S>Тем не менее разница есть: offline clients предполагают, что клиент способен самостоятельно жить в офлайне и что эта жизнь имеет какой-никакой смысл. Главный критерий здесь мобильность. S>А partial-disconnected apps это всего лишь способ снизить нагрузку на сеть/сервер и заодно реализовать сценарии, что трудно реализовать без локального кэша. Здесь данные постоянно находятся в памяти — in-memory db просто не нужна.
Все равно разницы нету. Разница между вашими offline clients и partial-disconnected apps только в персистентности кеша. Все остальное окажется точно таким же.
S>>>Для эффективной работы SyncServices требуют хоть-какой нибудь change tracking и (для провайдера искаропки) прямой доступ к таблицам. G>>Можно работать через сервисы, а change-tracking дается бесплатно. G>>Работает это все гораздо лучше, чем change-tracking датасетов.
S>Я как-то не понимаю, как чанжтракинг становится бесплатным. И каким боком он будет лучше датасетов. Разжуйте плиз.
Ничего не надо делать чтобы получить чанжтракинг. Лучше датасетов за счет полноценного SQL.
S>Вариант 2: EF + SQL CE + ADO.NET DataServices или SSDS (если их таки выпустят). Вы ведь это имели в виду
Не мешайте все в одну кучу.
Можно EF на серврере и ADO.NET DataServices на клиенте при наличиии постоянного соединения.
Для offline работы Sync Services. на клиенте и сервере можно использовать любую технологию доступа к данным.
SSDS вообще из другой оперы.
S>Деплоймент клиента: помимо фреймворка ставится sql ce — xcopy install уже не катит. // пустая придирка — решается install policies.
Фигня, SQL CE нормально xcopy ставится.
S>Особые требования к СУБД: S> 1) Наличие rowversion столбца.
Делается автоматически
S> 2) прямой доступ к таблицам или к представлениям.
Можно работать через вебсервисы.
S>А как вы собираетесь подружить SyncServices и DataServices? В мсдн нет ни слова по поводу их скрещивания. Первые используют датасеты для передачи данных между sql ce и провайдером, вторые — ef + wcf. Писать свой провайдер имхо получится слишком дорого. Если есть наводки — поделитесь.
Пока никак. Сейчас MS делает возможности иснхронизации через DataServices.
А вообще зачем их сомещать в Disconnected режиме?
S>>>Для partial disconnected типичный режим работы "коннектимся-заливаем небольшой объём данных-рабьотаем-синхронизация-работаем..." И здесь local db получается излишним оверкиллом. G>>не вижу почему будет оверкиллом? G>>Персистентность локальной копии данных + возможность обращаться к ней с помощью SQL (следовательно тот же EF или Linq2SQL) очень даже полезна.
S>Про оверкилл написал выше. Персистентность для partial connected нужна разве что для бэкапа на случай пропажи питания/выгрузки данных на случай нехватки памяти.
От частого повторения утверждение не становится истинным.
S>Для датасетов есть Linq2DataSets.
Ну и зачем он нужен?
Здравствуйте, gandjustas.
G>Все равно разницы нету. Разница между вашими offline clients и partial-disconnected apps только в персистентности кеша. Все остальное окажется точно таким же.
Нет. Есть принципиальные отличия: offline client — самостоятельное приложение, что обращается к серверу только для загрузки свежих данных/изредка запихнуть что-то своё (на десктопе как пример — оутглюк/рсс ридер). А Partial disconnected — всего лишь фронтенд к реальной системе. Он не предназначен для работы без соединения, а всего лишь не держит соединение постоянно открытым. Сценарии использования у софтин соответственно разные.
S>>Я как-то не понимаю, как чанжтракинг становится бесплатным. И каким боком он будет лучше датасетов. Разжуйте плиз. G>Ничего не надо делать чтобы получить чанжтракинг. Лучше датасетов за счет полноценного SQL.
Энееет. Вы писали "Работает это все гораздо лучше, чем change-tracking датасетов". Теперь расскажите как чанжтракинг выиграет от возможности выгребать данные при помощи sql? Или вы имеете в виду отслеживание изменений в анонимных типах — результатах запросов (которые by design readonly вообще-то) ?
Дальше. "Ничего не надо делать чтобы получить чанжтракинг.". Ничего не надо делать где? Если на сервере, чтобы получить свежие изменения — как раз надо. Если на клиенте — то датаадаптеры используют чанжтракинг датасетов и работают из коробки. Кстати в EF v2 будут Self-Tracking Entities — datarow вид сбоку (на самом деле ни разу не datarow конеш): http://blogs.msdn.com/efdesign/archive/2009/03/24/self-tracking-entities-in-the-entity-framework.aspx
Кажется, я просто вас здесь не понял...
G>Не мешайте все в одну кучу. G>Можно EF на серврере и ADO.NET DataServices на клиенте при наличиии постоянного соединения. G>Для offline работы Sync Services. на клиенте и сервере можно использовать любую технологию доступа к данным.
Ок, не будем. С какими технологиями доступа к данным работают Sync Services кроме дефолтного варианта "sql ce — sync services — sql server"?
Чтобы я не перевирал несказанное вами, предложите вашу альтернативу варианту 1
G>SSDS вообще из другой оперы.
Таки не совсем из другой оперы — ёжиков решено скрещивать. http://visualstudiomagazine.com/blogs/weblog.aspx?blog=3577:
A. We are looking into our future roadmap to make sure that Astoria [ADO.NET Data Services] can be leveraged on top of SDS and Entity Data Model continues to exist, and we will continue to provide for that through Astoria. We will continue to work with the Astoria framework and figure out how SDS can support that.
Как уже писалось, некритично — ставится один фиг через AD setup policies.
S>>Особые требования к СУБД: S>> 1) Наличие rowversion столбца. G>Делается автоматически
Изменение схемы базы данных не всегда допустимо. Точнее, как правило недопустимо.
S>> 2) прямой доступ к таблицам или к представлениям. G>Можно работать через вебсервисы.
Как я понял, sync services не умеют работать с вебсервисами. Даже если и умел бы, DataServices потребуют доступа к таблицам/view, что не всегда возможно — на тебе хранимки и не выкобенивайся... Насколько помню, других способов из коробки выставить БД как сервисы сейчас у МС нет. Пишем своё или ждём SDS?
S>>А как вы собираетесь подружить SyncServices и DataServices? В мсдн нет ни слова по поводу их скрещивания. Первые используют датасеты для передачи данных между sql ce и провайдером, вторые — ef + wcf. Писать свой провайдер имхо получится слишком дорого. Если есть наводки — поделитесь. G>Пока никак. Сейчас MS делает возможности иснхронизации через DataServices. G>А вообще зачем их сомещать в Disconnected режиме?
Имелось в виду именно использование DataServices для синхронизации через вебсервисы. DataServices пока поддерживает только ef. Потому и спросил.
G> G>От частого повторения утверждение не становится истинным.
Ну вы ведь не будете утверждать, что "EF<->sql ce<->syncservices (+возможно вебсервисы)<->sqlserver" эффективнее чем "DataSet<->sqlserver"? Основной режим работы "Залил данные — поработал — сохранил — залил данные...".
S>>Для датасетов есть Linq2DataSets. G>Ну и зачем он нужен?
Для псевдо-sql запросов к датасетам — как просили.
Здравствуйте, Sinix, Вы писали:
S>Извиняюсь за временное отсутствие наличия. Поскольку попытки изложить свои мысли связно и одним постом явно не находят понимания — вернёмся к цитатам на цитаты
Прекрасно, спасибо. S>
S>Часть из проверок можно производить локально, если сответствующие данные есть на клиенте. Эти проверки разумеется не дадут гарантированного результата, это не верификация — боже упаси, а только предварительное прощупывание на предмет возможных ошибок. С другой стороны, проверка данных в СУБД без внесения изменений тоже не даёт гарантий корректности данных, так что здесь оба способа предварительной проверки равноправны.
Ок, давайте поговорим о равноправии. Я уже предлагал — вы проигнорировали. Попробуем еще раз.
Раз мы отказываемся от стопроцентных гарантий, значит речь идет о вероятностном подходе. Никто не отрицает его полезность и важность. Но он тоже должен поддаваться учету и контролю.
Итак, у нас есть N данных. Из них K в кэше. Предположим, что существует ровно один дубликат. С вероятностью K/N он окажется в кэше (и проверка его найдет), с вероятностью 1-K/N он окажется вне кэша.
Итак, шансы на то, что "предварительное прощупывание" имет смысл, примерно равны K/N. Чему у вас равно это отношение?
Теперь давайте оценим полезность предварительной проверки в СУБД. Очевидно, что никакого шанса "пропустить" дубликат у нее нету, и единственный шанс облажаться — это получить дубликат за время T между проверкой и коммитом.
Предположим, остальные пользователи вносят изменения в интересующие нас данные с частотой F. При этом разнообразие значений примерно M, то есть вероятность для каждого отдельного изменения внести дубликат ~1/M. Итак, за время T было проведено T*F изменений, вероятность того, что ни одно из них не оказалось дубликатом = (1-1/M)^(T*F).
Значит, вероятность наличия дубликата растет со временем как 1-(1-1/M)^(T*F). Если сильно хочется, то можно разложить в ряд Тейлора по T, но и так понятно, что первый член будет равен T*F/M.
Итак, нам нужно сравнить P1 = K/N, и P2 = 1-(1-1/M)^(T*F).
S>1) Валидация с учётом всех невнесённых изменений на практике неосуществима (вы этого конеш не утверждали, я об этом писал — бред о когерентности кэшей именно к этому и относился)
Я повторно объясняю: нет задачи валидировать "с учетом невнесённых изменений". Невнесённых изменений вообще нет, с точки зрения теории транзакций. Потому, что если их не закоммитить, то их и не было никогда.
S>2) Примитивные проверки работают прекрасно, но плохо масштабируются из-за выноса кэша СУБД. Сложные непрактичны из-за резкого роста трафика — приходится строить и передавать граф изменённых сущностей.
Не понимаю, при чём тут кэш СУБД. Намекаю, что проверка на уникальность по индексированному ключу стоит порядка 0 обращений к диску. В плохих случаях — 1 обращение к диску.
S>Вроде никто не говорил о том, что локальные проверки отменяют или подменяют глобальные. Они их просто дополняют, а при аккуратном подходе хорошо снижают нагрузку на сервер. Ничего большего я и не утверждал вроде, нет?
Можно в студию формулы про снижение нагрузки? Мы же не стилисты, у нас "хорошо" должно иметь какое-то количественное выражение.
S>Нихт-нихт. Речь шла о том, что можно организовать работу пользователей с данными таким образом, что для каждого из них в базе нет никаких данных кроме тех, с которыми они работают.
Ну так я об этом и говорю — раз для него в базе нет никаких чужих данных, значит можно просто завести ему отдельную базу. S>Для этого нужно как можно больше конфликтов предупреждать локально. Здесь локальные проверки и рулят.
Откуда взялись конфликты?
S>Работать будет в двух сценариях: S>1. Если известно, что данных в кэше всегда будет достаточно для проведения проверки. Пример про уникальность по составному ключу (имена документов в папке) приводился выше.
А, я наверное не уловил про документы в папке. Вот теперь я начинаю понимать — это да, если гарантировать, что все Иваны у нас в кэше, то проверка уникальности фамилии даст корректный результат. А есть еще какие-нибудь проверки, которые можно вот так сегментировать? Только, пожалуйста, без абстракций. S>2. Если объём изменённых данных будет достаточно большим — массовые вставки или сеанс редактирования сложного графа объхектов.
Я не понимаю, что такое "сложный граф объектов" и почему при нём локальная проверка уникальности будет хоть сколько-нибудь полезна.
S>Дано: в некоторй папке живут подпапки a,b, имена подпапок должны различаться. S>Сначала a перенесли в b, затем создали новую папку с именем a и перенесли старую a в новую:
S>
S>a -> -> a (new) -> a (new)
S>b b b |-a (old)
S> |-a |-a (old) b
S>
S>В каждый отдельный момент граф находится в валидном состоянии. Теперь попробуйте внести изменения в базу данных, если change tracking хранит только 2 состояния: старое и новое.
Ок, давайте посмотрим, что произошло: S>
a -> a (new)
|-a (old)
b -> b
S>
простите, я не понимаю в чем проблема. Все изменения свелись к добавлению подпапки с именем a в папку с именем a.
Если важно сохранение суррогатных ключей, и СУБД не умеет откладывать проверки до окончания транзакции, то есть тупой и гарантированно рабочий алгоритм двухстадийного переименования.
В нем переименовываемые объекты сначала получают гарантированно уникальные имена, а потом уже получают настоящие.
Но как правило, СУБД откладывает такие проверки как минимум до конца стейтмента. Ну, а дальше уже вопрос техники — как обновить все объекты цикла за один стейтмент.
S>Варнинг он хоть должен выдать-то? Ещё раз: локальные ограничения нужны в первую очередь для обнаружения и исправления возможных ошибок ввода — чтобы пользователю не пришлось откручивать назад стек и вспоминать что именно вызвало ошибку при сохранении.
Чтобы не откручивать и не вспоминать — сообщения об ошибках должны давать достаточно информации. Сообщения типа "что-то сломалось" — сакс и бэдли независимо от применяемой технологии.
S>Дык вроде никто и не замахивался на /*завоевание галактики*/ написание сверхнадёжного клиента — речь шла именно о предотвращении ошибок пользователя. S>И с этой точки зрения запрет на одновременную работу нескольких товарищей под одним пользователем — довольно разумная вешь.
Во-первых, мне непонятно, каким именно образом несколько товарищей работают под одним пользователем по ошибке. Это типа "ой, я случайно набрала логин Юли и ее пароль?"
Во-вторых, зато есть масса полезных сценариев, где человек логинится под собой несколько раз.
S> Особенно если задачи, выполняемые пользователями распарралеливаются так, чтобы конфликты при редактировании возникали как можно реже. Ну и не стоит понимать запрет буквально — достаточно проверки с предупреждением.
Вообще-то сначала это фигурировало именно как математически достоверный факт, на который опиралась логика валидации.
S>А дальше начинается обычная оценка — какие проверки выгодней оосуществлять локально, а какие придётся делегировать субд. Для десктоп-клиентов число проверок, которые можно проводить локально обычно очень велика. Ещё раз: мы говорим не о 100%-й уверенности "у тебя здесь ошибка" а о предупреждении "при сохранении будут внесены неверные данные".
Можно формулу для "очень велика" в студию?
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, gandjustas.
G>>Все равно разницы нету. Разница между вашими offline clients и partial-disconnected apps только в персистентности кеша. Все остальное окажется точно таким же.
S>Нет. Есть принципиальные отличия: offline client — самостоятельное приложение, что обращается к серверу только для загрузки свежих данных/изредка запихнуть что-то своё (на десктопе как пример — оутглюк/рсс ридер). А Partial disconnected — всего лишь фронтенд к реальной системе. Он не предназначен для работы без соединения, а всего лишь не держит соединение постоянно открытым. Сценарии использования у софтин соответственно разные.
Ни одна из клиент-серверных технологий .NET не держит постоянное соектное соединение. Таким образом все многозвенные — Partial disconnected?
Вы неверное выбираете критерий разделения. Правильный критерий основан на "толщине" клиента. Если клиент толстый (тпе содержит в себе бизнес-логику), то он вполне может работать в отрыве от сервера некоторое время. Если клиент тонкий, то ему на каждое действие надо обращаться к серверу. Локальные проверки уникальности в закешированных данных тонкого клиента почти бессмысленны, слишком низкая точность у них.
Если у вас сильно разделены данные, так что разные пользователи не конфликтуют друг с другом, то вполне возможно создать offline клиент, который будет регулярно синхронизировать свои данные с сервером, а не использовать датасеты.
S>>>Я как-то не понимаю, как чанжтракинг становится бесплатным. И каким боком он будет лучше датасетов. Разжуйте плиз. G>>Ничего не надо делать чтобы получить чанжтракинг. Лучше датасетов за счет полноценного SQL. S>Энееет. Вы писали "Работает это все гораздо лучше, чем change-tracking датасетов". Теперь расскажите как чанжтракинг выиграет от возможности выгребать данные при помощи sql? Или вы имеете в виду отслеживание изменений в анонимных типах — результатах запросов (которые by design readonly вообще-то) ?
Не понял о чем вы. change-tracking на уровне БД получается. changeset можно сформировать даже если приложение не работало длительное время.
S>Дальше. "Ничего не надо делать чтобы получить чанжтракинг.". Ничего не надо делать где? Если на сервере, чтобы получить свежие изменения — как раз надо. Если на клиенте — то датаадаптеры используют чанжтракинг датасетов и работают из коробки. Кстати в EF v2 будут Self-Tracking Entities — datarow вид сбоку (на самом деле ни разу не datarow конеш): http://blogs.msdn.com/efdesign/archive/2009/03/24/self-tracking-entities-in-the-entity-framework.aspx S>Кажется, я просто вас здесь не понял...
Ага, я имел ввиду что программисту ничего делать не надо.
G>>Не мешайте все в одну кучу. G>>Можно EF на серврере и ADO.NET DataServices на клиенте при наличиии постоянного соединения. G>>Для offline работы Sync Services. на клиенте и сервере можно использовать любую технологию доступа к данным.
S>Ок, не будем. С какими технологиями доступа к данным работают Sync Services кроме дефолтного варианта "sql ce — sync services — sql server"? S>Чтобы я не перевирал несказанное вами, предложите вашу альтернативу варианту 1
Искаропки — ни с какими. Но можно очень быстро сделать провайдер и адаптер для лююбой БД (указать строку соединения и несколько команд).
S>Как уже писалось, некритично — ставится один фиг через AD setup policies.
Неправда. xcopy достаточно для sqlce.
S>>>Особые требования к СУБД: S>>> 1) Наличие rowversion столбца. G>>Делается автоматически S>Изменение схемы базы данных не всегда допустимо. Точнее, как правило недопустимо.
А кто разработчик?
S>>> 2) прямой доступ к таблицам или к представлениям. G>>Можно работать через вебсервисы. S>Как я понял, sync services не умеют работать с вебсервисами.
Неправльно поняли, очень даже умеет.
S>Даже если и умел бы, DataServices потребуют доступа к таблицам/view, что не всегда возможно — на тебе хранимки и не выкобенивайся...
Ну если у вас такие проблемы, то кроме датасетов вам мало что поможет.
S>Насколько помню, других способов из коробки выставить БД как сервисы сейчас у МС нет. Пишем своё или ждём SDS?
sds совсем из другой оперы.
S>>>А как вы собираетесь подружить SyncServices и DataServices? В мсдн нет ни слова по поводу их скрещивания. Первые используют датасеты для передачи данных между sql ce и провайдером, вторые — ef + wcf. Писать свой провайдер имхо получится слишком дорого. Если есть наводки — поделитесь. G>>Пока никак. Сейчас MS делает возможности иснхронизации через DataServices. G>>А вообще зачем их сомещать в Disconnected режиме? S>Имелось в виду именно использование DataServices для синхронизации через вебсервисы. DataServices пока поддерживает только ef. Потому и спросил.
Через WCF и сейчас возможно.
G>> G>>От частого повторения утверждение не становится истинным. S>Ну вы ведь не будете утверждать, что "EF<->sql ce<->syncservices (+возможно вебсервисы)<->sqlserver" эффективнее чем "DataSet<->sqlserver"? Основной режим работы "Залил данные — поработал — сохранил — залил данные...".
Еще раз говорю что это возможно только когда один дексктопный клиент на одну базу.
S>Ок, давайте поговорим о равноправии. Я уже предлагал — вы проигнорировали. Попробуем еще раз. S>Раз мы отказываемся от стопроцентных гарантий, значит речь идет о вероятностном подходе. Никто не отрицает его полезность и важность. Но он тоже должен поддаваться учету и контролю.
Disclaimer уже был:
А дальше начинается обычная оценка — какие проверки выгодней оосуществлять локально, а какие придётся делегировать субд. Для десктоп-клиентов число проверок, которые можно проводить локально обычно очень велика. Ещё раз: мы говорим не о 100%-й уверенности "у тебя здесь ошибка" а о предупреждении "при сохранении будут внесены неверные данные".
...
Главная грабля в написании partial disconnected софта — соблюдать баланс, чтобы с одной стороны клиент не захлебнулся от жадности, а с другой — не нагружать по возможности сервер. При должной степени аккуратности получается дешёвое и масштабируемое решение.
Про "очень велика": типичные сценарии приводил:
1. Если известно, что данных в кэше всегда будет достаточно для проведения проверки. Пример про уникальность по составному ключу (имена документов в папке) приводился выше.
2. Если объём изменённых данных будет достаточно большим — массовые вставки или сеанс редактирования сложного графа объхектов.
Как подвид сценария 2 — всякие ограничения, накладываемые бизнес-логикой. Они как раз обычно очень хорошо ложатся на данные в кэше. Нужны примерно затем же что и code constraints — для нахождения косяков в БЛ.
Мне казалось, что таких отмазок достаточно для того, чтобы свернуть обсуждение на тему "насколько эффективна такая оценка" — it depends
S>Итак, нам нужно сравнить P1 = K/N, и P2 = 1-(1-1/M)^(T*F).
Уже писалось — на всякий: в общем случае эффективней обратиться к СУБД. в случае когда у нас данных на клиенте достаточно — эффективней локальная проверка. Это вроде очевидно
S>>2) Примитивные проверки работают прекрасно, но плохо масштабируются из-за выноса кэша СУБД. Сложные непрактичны из-за резкого роста трафика — приходится строить и передавать граф изменённых сущностей. S>Не понимаю, при чём тут кэш СУБД. Намекаю, что проверка на уникальность по индексированному ключу стоит порядка 0 обращений к диску. В плохих случаях — 1 обращение к диску.
Сталкивался на практике: 50-70 мелких запросов поднимали по странице в кэш (повезло с распределением ), вытесняя страницы другого индекса, что использовался для жойна в параллельных запросах. А так как оптимайзер выбирал nested loops вместо hash join, который терпимей к недостатку памяти, производительность конкретно проседала. Особенно часто подобные косяки проявлялись на серверах, где живёт куча баз и памяти не хватает по-страшному.
S>>Вроде никто не говорил о том, что локальные проверки отменяют или подменяют глобальные. Они их просто дополняют, а при аккуратном подходе хорошо снижают нагрузку на сервер. Ничего большего я и не утверждал вроде, нет? S>Можно в студию формулы про снижение нагрузки? Мы же не стилисты, у нас "хорошо" должно иметь какое-то количественное выражение.
Дык тут это — цифры нужны корректные. То что проверял лично года три назад:
Небольшая софтина/редактор типа словарика. Писалась специально для оценки стоимости регулярных обращений к серверу. Она рандомно выполняла некоторые действия над сущностями раз в 1-20 секунд и раз в 5 минут выполняла синхронизацию. При подходе с датасетами сервер держал порядка 150-200 одновременных подключений (дёргалось с 5 машин, пришлось ставить обновление непрерывно), каждое обращение занимало 1-5 секунд. Тормоза были с сетью — постоянно очередь у сетевого контроллера, процессор (celeron 1'7) — ~60%, память почти забита (памяти — 512 мб, база была сгенерена на 3 с чем-то гигов), объём отдаваемых данных на один запрос — 100-300кб.
Для EF|Linq2SQL проверка ессно не проводилась — не те времена Вместо этого данные подгружались кусочками по требованию — имитировалась подгрузка данных по мере навигации + временами дёргались запросы по текстовым столбцам — типа поиск
При полусотне коннектов база регулярно накрывалась медным тазом из-за взаимоблокировок. После убирания запросов на обновление, баттлнеком становилась очередь диска плюс память.
Могу восстановить софтинки (хотя магии там никакой нет) и прогнать по новой.
Если хочется цифр — берём теорию обслуживания (чесслово не знаю как оно зовётся по взрослому, дядечка что нам читал матобеспечение уверял что именно так) и подставляем. Время обслуживания 1-5 сек против 40-120 сек, интервал обращения — 5 минут.
S>>Нихт-нихт. Речь шла о том, что можно организовать работу пользователей с данными таким образом, что для каждого из них в базе нет никаких данных кроме тех, с которыми они работают. S>Ну так я об этом и говорю — раз для него в базе нет никаких чужих данных, значит можно просто завести ему отдельную базу. S>>Для этого нужно как можно больше конфликтов предупреждать локально. Здесь локальные проверки и рулят. S>Откуда взялись конфликты?
То, что большинство пользователей работают с практически непересекающимися диапазонами данных не значит, что пересечений этих нет. Зачем их разделять?
S>>Работать будет в двух сценариях: S>>1. Если известно, что данных в кэше всегда будет достаточно для проведения проверки. Пример про уникальность по составному ключу (имена документов в папке) приводился выше.
S>А, я наверное не уловил про документы в папке. Вот теперь я начинаю понимать — это да, если гарантировать, что все Иваны у нас в кэше, то проверка уникальности фамилии даст корректный результат. А есть еще какие-нибудь проверки, которые можно вот так сегментировать? Только, пожалуйста, без абстракций.
Да, FK (естественно ) и кастомные ограничения, что накладываются бизнес-логикой (типа не можешь создавать больше 5 папок)
S>>2. Если объём изменённых данных будет достаточно большим — массовые вставки или сеанс редактирования сложного графа объхектов. S>Я не понимаю, что такое "сложный граф объектов" и почему при нём локальная проверка уникальности будет хоть сколько-нибудь полезна.
Да любой большой UOW, что подразумевает участие пользователя приводит к куче изменений/удалений/созданию новых объектов. Корректность этих изменений выгодно проверять на месте — например, что взаказе не дублируются продукты (баг, должно увеличиться количество), что в результате пользователь не попросит больше бонусов, что ему положено и т.п.
Проверка таких "бизнес-ограничений" затрагивает кучу сущностей (особенно если данные нормализованы). И для более-менее надёжной проверки нужно, чтобы даные были когерентными (псевдо-repeatable read, если хотите). А согласованность локальных данных проще всего достигается с помошью локадьного кэша.
S>простите, я не понимаю в чем проблема. Все изменения свелись к добавлению подпапки с именем a в папку с именем a. S>Если важно сохранение суррогатных ключей, и СУБД не умеет откладывать проверки до окончания транзакции, то есть тупой и гарантированно рабочий алгоритм двухстадийного переименования.
Там не сохранение суррогатных ключей, а нарушение составных естественных ключей шло. Проблема была в сохранении кучи разнотипных сущностей (в однин стейтмент не уложишься, субд ms sql — отложить проверки нельзя), из-за грязных данных (хотя формально они были чистыми) регулярнейше возникали эдакие циклы, когда старая папка (на самом деле не папка) с таким именем должна была переместиться в новосозданную папку, которую нельзя было создать из-за старой.
Причём на вход приходил датасет, по сути — два списка: изменённые сущности в исходном состоянии и изменённые сущности в текущем состоянии. В сам процесс построения обоих списков вмешиваться было нежелательно, максимум что было разрешено — подписываться на сооответствующие события изменения строк.
По полурелигиозным причинам требовалось подобные косяки находить сразу, до внесения в базу.
S>Чтобы не откручивать и не вспоминать — сообщения об ошибках должны давать достаточно информации. Сообщения типа "что-то сломалось" — сакс и бэдли независимо от применяемой технологии.
Допустим в приведённом выше примере выдавалось текстовое описание цикла зависимостей (по гиперссылкам переходило к нужным сущностям) + предложение оставить как есть (субд разберётся) либо отменить изменения в любой из сущностей на выбор. При наличии информации об ограничениях довольно простая штука.
S>Во-первых, мне непонятно, каким именно образом несколько товарищей работают под одним пользователем по ошибке. Это типа "ой, я случайно набрала логин Юли и ее пароль?" S>Во-вторых, зато есть масса полезных сценариев, где человек логинится под собой несколько раз.
Самый типичный сценарий — товарищ логинится на другой машине, тут же выскакивает вопрос — "вы уже залогинены там-то. завершить сеанс(ы) (выбирается нужные)/проигнорировать" + галочка "запомнить". Естественно, текст куда внятней
S>> Особенно если задачи, выполняемые пользователями распарралеливаются так, чтобы конфликты при редактировании возникали как можно реже. Ну и не стоит понимать запрет буквально — достаточно проверки с предупреждением. S>Вообще-то сначала это фигурировало именно как математически достоверный факт, на который опиралась логика валидации.
У нас тут походу самый большой затык. Поскольку в мозгах у меня сейчас затый ничуть не меньший — отложим до завтра, ок?
Здравствуйте, Tom, Вы писали:
ili>>а что сразу в типизированый бизнес-объект мапить нихт? Tom>Мая твая нихт панимать
я так понял, что под "оберткой" имеется ввиду какая-то обертка над бизнес объектом.. вот зачем это я и не понимаю..
может я вообще не понял что есть "обертка"... вот интересно стало... что это и зачем оно?
ili>я так понял, что под "оберткой" имеется ввиду какая-то обертка над бизнес объектом.. вот зачем это я и не понимаю.. ili>может я вообще не понял что есть "обертка"... вот интересно стало... что это и зачем оно?
Есть стора или запрос которая возвращает поля A, B, C. Обёртка — это класс с такими полями и соответствующими типами данных.
Здравствуйте, Tom, Вы писали:
Tom>Есть стора или запрос которая возвращает поля A, B, C. Обёртка — это класс с такими полями и соответствующими типами данных.
а что потом с этой оберткой делается?
я просто втолк не возьму, это класс модели домена?
ili>а что потом с этой оберткой делается?
Например выводится на ASP.NET страничке
ili>я просто втолк не возьму, это класс модели домена?
Нет конечно. И я незнаю что такое класс модели домена. Знаю что такое класс модели предметной области
Здравствуйте, Tom, Вы писали:
ili>>я просто втолк не возьму, это класс модели домена? Tom>Нет конечно. И я незнаю что такое класс модели домена. Знаю что такое класс модели предметной области
домен и предметная область — синонимы в данном контексте, но "домен" писать короче
так вот я не понимаю, зачем нужны обертки, почему нельзя пользоваться классами модели предметной области?...
ili>так вот я не понимаю, зачем нужны обертки, почему нельзя пользоваться классами модели предметной области?...
И я не понимаю где мне их брать, когда для данной вью их просто нет. Например когда стора возвращает агрегатЫ
Или обьекты предметной области универсальный ответ на "Ответ на главный вопрос жизни, вселенной и всего такого" (c) Дуглас Адамс ?
Здравствуйте, Tom, Вы писали:
ili>>так вот я не понимаю, зачем нужны обертки, почему нельзя пользоваться классами модели предметной области?... Tom>И я не понимаю где мне их брать, когда для данной вью их просто нет. Например когда стора возвращает агрегатЫ
отчет? а почему дата-тейбл не подходит? (мне и вправду интересно)
Tom>Или обьекты предметной области универсальный ответ на "Ответ на главный вопрос жизни, вселенной и всего такого" (c) Дуглас Адамс ?
42
VD>>Сдается мне триггеры на полноценном языке могли бы пригодиться многим. IB>А мне сдается что нет. Ни триггеры, ни хранимки. Всю серьезную логику не связанную непосредственно с SQL-ем, все равно проще удобнее и правильнее делать в прикладном коде.
А чем хранимки на дотнете не прикладной код? Да еще учитывая возможность генерации их "на лету".
Здравствуйте, Tom, Вы писали:
ili>>отчет? а почему дата-тейбл не подходит? (мне и вправду интересно) Tom>Всегда лучше иметь что то типизированное, а не DataTable
оно, конечно, пожалуй так, но мне вот, не приходилось сталкиваться с проблемами при использовании DataTable для отчетов. тебе (как я понял) приходилось, вот мне и интересно, что там было, дабы на те же грабли не наступать.
Здравствуйте, vdimas, Вы писали:
V>А чем хранимки на дотнете не прикладной код? Да еще учитывая возможность генерации их "на лету".
Обилием проблем с поддержкой и развертыванием. Связываться с этим имеет смысл если App-сервера нет ни в каком виде, а очень нужно, если же хоть какой-то сервер приложений есть, то проще все вынести туда.
V>>А чем хранимки на дотнете не прикладной код? Да еще учитывая возможность генерации их "на лету". IB>Обилием проблем с поддержкой и развертыванием.
Странно, столько доки и примеров на эту тему, что показалось, будто вопрос вполне обыденный.
IB>Связываться с этим имеет смысл если App-сервера нет ни в каком виде, а очень нужно, если же хоть какой-то сервер приложений есть, то проще все вынести туда.
Выражу исключительно моё ИМХО, но выделенный стателесс апп-сервер — это бесполезная прослойка из лишнего процесса, учитывая возможность запихать логику стателесс-алгоритмов прямо в процесс SQL-сервера. А еще когда на этом выделенном апп-сервере начинают кеши когерентные наверчивать, то вообще, спасайся кто может. Причём, кеши эти абсолютно бесполезны, если (как это часто бывает) апп-сервер делают заодно с веб-мордой.
Здравствуйте, vdimas, Вы писали:
V>Странно, столько доки и примеров на эту тему, что показалось, будто вопрос вполне обыденный.
Доками и примерами геморрой не лечится.
V>Выражу исключительно моё ИМХО, но выделенный стателесс апп-сервер — это бесполезная прослойка из лишнего процесса, учитывая возможность запихать логику стателесс-алгоритмов прямо в процесс SQL-сервера.
Ты только геморрой с этим связанный не учитываешь. А учитывая, что App сервер и так есть и причем как правило стейтлесс, то лучше уж логику там держать.
V>А еще когда на этом выделенном апп-сервере начинают кеши когерентные наверчивать,
Это уже не стейтлесс получается.
IB>А учитывая, что App сервер и так есть и причем как правило стейтлесс, то лучше уж логику там держать.
Дык, я и хочу понять — почему это оно "и так есть" до сих пор?
Вернее, я прекрасно знаю, так сложилось из-за того, что императив противопоказан T-SQL, а расчётные формулы бывают изощренные и даже рекурсивные. А еще все любят типизированность, решарпер и XML.
Так же прекрасно помню как плевались юзвери более 10 лет назад, когда ту же самую программу переводили с сетевых MDB-файлов на app-сервера + MS SQL, ибо привыкли получать результат за долю секунды, что глаз не успевал реагировать, а не за 1..2сек. Сейчас не столь актуально, но всё-равно... "лишний" stateless сервак до пол-секунды отклика в среднем добавляет при нагрузке конкретному клиенту (там же две задержки в каждую сторону, два лишних преобразования данных, две лишних межпроцессорных коммуникации). А это на глаз весьма заметно в сравнении с прямым подключением к SQL-серверу, которое отрабатывает субъективно мгновенно на простых выборках (отчёты и прочую сложновычисляемую хрень ввиду не имею, речь о поддержке оперативной набивки/обработки).
И с каких это пор "гемморой" — аргумент? В MS SQL 7 даже колонку, помнится, переименовать в EM сложно было, заводили рядом другую, тут же создавали и запускали запрос копирование столбца, старый дропали, и никто на гемморой не жаловался... И статистику исключительно руками вертели и много еще чего. А сейчас всё тоже самое, только "само", расслабляет наверно?
Самый бенефит, конечно же в том, что этот код в процессе сервера крутится, и в нужных случаях гемморой — не самая большая плата. Мне не очень нравится дизайн System.Data, он совершенно не пригоден для статической типизации, более того, провоцирует своим дизайном на постоянный боксинг примитивных типов, но это всё частности. Я лет еще 5 назад задекларировал "идеальный" для себя апп-сервер, который с базой в одном процессе. Правда, тут Магоммет подошёл, а не гора, но опять же, не суть.
И кстати, в OODB (ничего, что на твой мозоль? я не сильно) есть один такой момент, который многие заметили, но еще большее кол-во предпочло пропустить — это высокая статическая типизированность (для разработчика). Оставь в них только реляционную классику, возьми от них типизированный интерфейс к API сервера при написании своих "хранимок", и получим то, что мне не хватало последние лет 10.
Здравствуйте, vdimas, Вы писали:
V>Дык, я и хочу понять — почему это оно "и так есть" до сих пор?
Очень просто. Каждый должен заниматься своим делом. Вот дело БД — хранить данные, но ни в коем случае не хостить сервера приложений..
V> "лишний" stateless сервак до пол-секунды отклика в среднем добавляет при нагрузке конкретному клиенту (там же две задержки в каждую сторону, два лишних преобразования данных, две лишних межпроцессорных коммуникации).
Я тебя умоляю.. =) По сравнению с латентностью сети и временем обработки запросов БД — это другой порядок малости, в микроскоп не заметишь.
V>Самый бенефит, конечно же в том, что этот код в процессе сервера крутится, и в нужных случаях гемморой — не самая большая плата.
Я тебя разочарую, быстрее он от этого не сильно становится. Я не помню, как там точно SQLOS хостит дотнетные процессы, но именно за счет того что формально это дело хостится в сиквеле выигрыш не большой.
V>Я лет еще 5 назад задекларировал "идеальный" для себя апп-сервер, который с базой в одном процессе.
Ты не стой стороны проблему решаешь. От того что ты все в одно место запихнешь, легче не станет, стабильность и стоимость сопровождения вырастут настолько, что сам рад не будешь.
Если проблема в плохих способах взаимодействия между .Net и БД, значит надо улучшать способ взаимодействия, а не уходить от проблемы запихивая все в одно место.
V>И кстати, в OODB (ничего, что на твой мозоль? я не сильно) есть один такой момент, который многие заметили, но еще большее кол-во предпочло пропустить — это высокая статическая типизированность (для разработчика). Оставь в них только реляционную классику, возьми от них типизированный интерфейс к API сервера при написании своих "хранимок", и получим то, что мне не хватало последние лет 10.
Здравствуйте, IB, Вы писали:
V>> "лишний" stateless сервак до пол-секунды отклика в среднем добавляет при нагрузке конкретному клиенту (там же две задержки в каждую сторону, два лишних преобразования данных, две лишних межпроцессорных коммуникации). IB>Я тебя умоляю.. =) По сравнению с латентностью сети и временем обработки запросов БД — это другой порядок малости, в микроскоп не заметишь.
Латентность сети 100-150ms норма на другой конец земного шара даже из нашей провинции, а про время обработки рассказывать не надо. Оперативные данные — они всегда небольшие по объёму (если правильно делать), в отличие от всевозможных "исторических", но у отчётности, как уже замечал, свои требования и может быть совсем своя огранизация.
V>>Самый бенефит, конечно же в том, что этот код в процессе сервера крутится, и в нужных случаях гемморой — не самая большая плата. IB>Я тебя разочарую, быстрее он от этого не сильно становится. Я не помню, как там точно SQLOS хостит дотнетные процессы, но именно за счет того что формально это дело хостится в сиквеле выигрыш не большой.
V>>Я лет еще 5 назад задекларировал "идеальный" для себя апп-сервер, который с базой в одном процессе. IB>Ты не стой стороны проблему решаешь. От того что ты все в одно место запихнешь, легче не станет, стабильность и стоимость сопровождения вырастут настолько, что сам рад не будешь. IB>Если проблема в плохих способах взаимодействия между .Net и БД, значит надо улучшать способ взаимодействия, а не уходить от проблемы запихивая все в одно место.
Да нет, проблема в том, что мы дублируем описание сущностей, и раздражает в случае сценария stateless — это именно практически 1-в-1 дублирование, чем не обезьянья работа? И про кодогенераторы тоже все знают, как и про разрыв второго рода при рефакторинге.
Далее, существующая бинарная сериализация дотнет крайне неэффективная, медленная и прожорливая в ресурсах, ибо боксит даже примитивные типы, да и вообще создаёт даже для простейших классов кучу промежуточных объектов. Нормальные сравнительные результаты показывает только при сериализации массивов примитивных типов относительно большой длины, в случае же сериализации большого сомна тех самых "типизированных сущностей" — затраты тиков проца только на сериализацию/десериализацию раз в 50 превышают "оптимальную" сериализацию (т.е. то, что примерно делает сервак SQL, и этот порядок замеряли). И вот для тех самых случаев, где требуется большое кол-во мелких выборок для сотен и более клиентов, одни только "нефункциональные" затраты апп-сервака сопоставимы с полезными действиями БД (в "разогретом" состоянии, конечно). Понятное дело, "ставь лишнюю железку и не парься", как все и делают, но как-то это всё попахивает лажей фундаментального плана.
Насчёт "улучшать способ взаимодействия", дык и этим занимался однажды, перелопачивая на ручную сериализацию, где те самые 50 раз в выигрыше и поимел, и заметный субъективный прирост отклика тоже. Но там сущностей было чуть более трёх десятков (правда, структура весьма и весьма развесиста на них), и делалось это уже после "окончательных рефакторингов". А мы то понимаем, как это всё смешно звучит на самом деле. Вот занимаясь такого рода херней, не покидает ощущение какой-то фундаментальной недоработки на ровном месте. Старые добрые OLE DB интерфейсы кажутся гораздо более продуманными в плане эффективного манипулирования данными, чем предложенный System.Data и далее в глубь по нейспейсам.
---------
И просто поверь, когда GUI откликается практически мгновенно, или тормозит секунду-другую, как в браузере, это ОЧЕНЬ большая разница. Привыкнув к первому, с трудом подавляешь раздражение, работая со вторым.
Здравствуйте, vdimas, Вы писали:
V>Латентность сети 100-150ms норма на другой конец земного шара даже из нашей провинции,
И ты хочешь сказать, что передача через границу процесса занимает сравнимое время?
V> а про время обработки рассказывать не надо. Оперативные данные — они всегда небольшие по объёму (если правильно делать),
Какиеб они ни были маленькие — их обработка все равно занимает время большее, чем сериализация объекта в плоскую структуру и обратно.
V>Да нет, проблема в том, что мы дублируем описание сущностей, и раздражает в случае сценария stateless — это именно практически 1-в-1 дублирование, чем не обезьянья работа? И про кодогенераторы тоже все знают, как и про разрыв второго рода при рефакторинге.
Тут ты себе противоречишь.. Ты только что утверждал, что готов на любой геморрой, лишь бы скорость была, а тут выясняется, что проблема все-таки в геморрое..
V>Далее, существующая бинарная сериализация дотнет крайне неэффективная, медленная и прожорливая в ресурсах, ибо боксит даже примитивные типы, да и вообще создаёт даже для простейших классов кучу промежуточных объектов.
А это-то тут причем? Мы вроде только про сиквел беседуем.
V> Нормальные сравнительные результаты показывает только при сериализации массивов примитивных типов относительно большой длины, в случае же сериализации большого сомна тех самых "типизированных сущностей" — затраты тиков проца только на сериализацию/десериализацию раз в 50 превышают "оптимальную" сериализацию (т.е. то, что примерно делает сервак SQL, и этот порядок замеряли). И вот для тех самых случаев, где требуется большое кол-во мелких выборок для сотен и более клиентов, одни только "нефункциональные" затраты апп-сервака сопоставимы с полезными действиями БД (в "разогретом" состоянии, конечно). Понятное дело, "ставь лишнюю железку и не парься", как все и делают, но как-то это всё попахивает лажей фундаментального плана.
То, что стандартный BinarySerializer кривой до нельзя — это факт известный, но я не могу понять, причем тут сиквел и какое это вообще отношение к БД имеет, ты уж не мешай все в одну кучу... Или ты по случаю первого апреля считаешь, что сиквел с приложением посредством стандартной бинарной сериализации типизированных объектов общается? Завязывай, уже второе. =)
V>Насчёт "улучшать способ взаимодействия", дык и этим занимался однажды, перелопачивая на ручную сериализацию, где те самые 50 раз в выигрыше и поимел, и заметный субъективный прирост отклика тоже.
Ну, MS тоже не пальцем деланый — бинарную сериализацию конечно индусы писали, а вот WCF-ные сервисы, в основном все-таки ребята с правильными руками, поэтому, в частности, взаимодействие между процессами посредством WCF сравнимо по скорости с DCOM, так что с сериализацией там все в порядке.
V> Старые добрые OLE DB интерфейсы кажутся гораздо более продуманными в плане эффективного манипулирования данными, чем предложенный System.Data и далее в глубь по нейспейсам.
То есть, ты свою собственную обертку поверх OLDB написал и получил серъезный выигрыш в производительности? "Не верю" (с)
V>И просто поверь,
Просто — не буду.
V>когда GUI откликается практически мгновенно, или тормозит секунду-другую, как в браузере, это ОЧЕНЬ большая разница.
То есть, по твоему браузер тормозит из за того, что IIS выполняется в процессе отдельном от сиквела?
Здравствуйте, IB, Вы писали:
IB>Очень просто. Каждый должен заниматься своим делом. Вот дело БД — хранить данные, но ни в коем случае не хостить сервера приложений..
Кстати, если отбросить геморрой и другие проблемы, то почему бы не хостить сервер приложений в том же процессе, что и сиквел? Производительности и масштабируемости это только помогло бы.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
V>>Да нет, проблема в том, что мы дублируем описание сущностей, и раздражает в случае сценария stateless — это именно практически 1-в-1 дублирование, чем не обезьянья работа? И про кодогенераторы тоже все знают, как и про разрыв второго рода при рефакторинге. IB>Тут ты себе противоречишь.. Ты только что утверждал, что готов на любой геморрой, лишь бы скорость была, а тут выясняется, что проблема все-таки в геморрое..
Кому какой ближе, тебе, судя по всему, сопроводительный, мне — в разработке. Хотя, если деплоить базу не скриптами, а маунтить заготовки баз, то как бы гемморроя слегка поменьше (по крайней мере мы деплоим именно так).
IB>То, что стандартный BinarySerializer кривой до нельзя — это факт известный, но я не могу понять, причем тут сиквел и какое это вообще отношение к БД имеет, ты уж не мешай все в одну кучу... Или ты по случаю первого апреля считаешь, что сиквел с приложением посредством стандартной бинарной сериализации типизированных объектов общается? Завязывай, уже второе. =)
Гхм, вообще-то абзацем выше уже был контекст про сервер приложений, так что весь этот абзац к нему и относился. А пихать WCF туда, где 90% банального stateless CRUD, т.е. "прослойка" практически без самостоятельного функционала — это перебор, ИМХО. Такая прослойка должна быть как можно тоньше. Хотя, для ненагрузочных сценариев, чтобы "быстро на коленке собрать", почему бы и нет.
Опять же, а какой избыток данных мы будем гонять на другой конец земного шара, и главное — ради чего?
Хотя, это мы отвлеклись от темы. Просто странный наблюдается парадокс: middleware становится всё мощнее, изощреннее и конфигурируемее, что чуть ли не мышкой серверный код накидывается (утрирую, но оно близко). И чем дальше этот процесс, тем больше народ склоннен "отуплять" СУБД. И нафига тогда кол-во возможностей для построения сервера приложений именно на СУБД растёт с каждым годом? Когда-то рванул Оракл в этом направлении, MS гарцает и даже перегонит скоро, а бывшие аппологеты максимально-внутри СУБД-ориентированной обработки данных уже начинают советовать WCF по каждому чиху. Наверно я опять чего-то не понимаю?
V>>Насчёт "улучшать способ взаимодействия", дык и этим занимался однажды, перелопачивая на ручную сериализацию, где те самые 50 раз в выигрыше и поимел, и заметный субъективный прирост отклика тоже. IB>Ну, MS тоже не пальцем деланый — бинарную сериализацию конечно индусы писали, а вот WCF-ные сервисы, в основном все-таки ребята с правильными руками, поэтому, в частности, взаимодействие между процессами посредством WCF сравнимо по скорости с DCOM, так что с сериализацией там все в порядке.
V>> Старые добрые OLE DB интерфейсы кажутся гораздо более продуманными в плане эффективного манипулирования данными, чем предложенный System.Data и далее в глубь по нейспейсам. IB>То есть, ты свою собственную обертку поверх OLDB написал и получил серъезный выигрыш в производительности? "Не верю" (с)
Нет, я сравниваю инфтерфейсы и способы извлечения данных. Максимально просто и эффективно — да и как по другому в интерфейсах, основная задача которых переливать как можно большее кол-во данных с как можно меньим участием процессора? В противовес этому, на код AdoDB.Net — провайдеров в рефлекторе без слёз смотреть порой невозможно.
Сам сценарий раньше был какой? Заготавливаем источники для всех колонок (смещения или ридеры столбцов), однократно валидируем совпадение типов с ожидаемыми, а потом в цикле тупо льём объемы, и трудоёмкость получается сравнима с memcpy. А сейчас просто пройдись по любому XXXDataReader::ReadIn32(), и ужаснись всей этой безразмерной цепочке кода, которая сопровождает чтение каждого поля каждой строки.
V>>когда GUI откликается практически мгновенно, или тормозит секунду-другую, как в браузере, это ОЧЕНЬ большая разница. IB>То есть, по твоему браузер тормозит из за того, что IIS выполняется в процессе отдельном от сиквела?
Нет, браузер как пример, а тормозит он толи из-за множественных запросов на одну страницу, то ли от природы формирования современных php/jsp/asp страниц, толи еще от чего — не суть, когда гуй не браузерный, то пользователь ожидает адекватную реакцию.
Здравствуйте, VladD2, Вы писали:
VD>Кстати, если отбросить геморрой и другие проблемы, то почему бы не хостить сервер приложений в том же процессе, что и сиквел? Производительности и масштабируемости это только помогло бы.
Это вряд ли, так как если по уму, то один сиквел может держать 3-4 app-сервера, хотя от задач конечно зависит.
Здравствуйте, vdimas, Вы писали:
V>Далее, существующая бинарная сериализация дотнет крайне неэффективная...
А причем тут бинарная сериализация дотнета? Если ты из сервера приложений используешь запросы к сиквелу, то пользуешся его форматом стрима который очень эффективен.
V>Насчёт "улучшать способ взаимодействия", дык и этим занимался однажды, перелопачивая на ручную сериализацию, где те самые 50 раз в выигрыше и ...Старые добрые OLE DB интерфейсы кажутся гораздо более продуманными в плане эффективного манипулирования данными, чем предложенный System.Data и далее в глубь по нейспейсам.
Ты меня извини. Я теоретически с тобой за одно, в том смысле, что тоже считаю, что сервер приложений встроенный в СБУД — это хорошая идея. Но то что ты говоришь — это мягко говоря заблуждения. Причем тут System.Data?
IDataReader самый эффективный способ чтения данных из MS SQL из имеющихся в природе. Никакие OLE DB провайдеры и рядом не валялись.
V>--------- V>И просто поверь, когда GUI откликается практически мгновенно, или тормозит секунду-другую, как в браузере, это ОЧЕНЬ большая разница. Привыкнув к первому, с трудом подавляешь раздражение, работая со вторым.
Кому нужна вера? Есть методы исследования, измерения, тесты...
Создай примитивный тест или просто почитай статьи с этого сайта. В них такие тесты уже делались. Причем много лет назад.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, vdimas, Вы писали:
V> Хотя, если деплоить базу не скриптами, а маунтить заготовки баз, то как бы гемморроя слегка поменьше (по крайней мере мы деплоим именно так).
Заготовками баз обратную совместимость не обеспечишь.
V>Гхм, вообще-то абзацем выше уже был контекст про сервер приложений, так что весь этот абзац к нему и относился. А пихать WCF туда, где 90% банального stateless CRUD, т.е. "прослойка" практически без самостоятельного функционала — это перебор, ИМХО. Такая прослойка должна быть как можно тоньше.
Это ты просто WCF не видел, наверное.. =) При желании — тоньше не придумаешь, не вижу никаких проблем запихнуть его всюду, где хоть какая-то передача данных, особенно тупой CRUD.
V> Хотя, для ненагрузочных сценариев, чтобы "быстро на коленке собрать", почему бы и нет.
Как раз с нагрузочными-то никаких проблем.. )
V>Хотя, это мы отвлеклись от темы. Просто странный наблюдается парадокс: middleware становится всё мощнее, изощреннее и конфигурируемее, что чуть ли не мышкой серверный код накидывается (утрирую, но оно близко). И чем дальше этот процесс, тем больше народ склоннен "отуплять" СУБД.
В целом да, но пока я не вижу в этом ничего плохого.
V> а бывшие аппологеты максимально-внутри СУБД-ориентированной обработки данных уже начинают советовать WCF по каждому чиху.
Если это на меня намек, то я всегда был апологетом здравого смысла.. И был одинаково против как всего пихания в базу, так и выпихивания всего из базы. Есть логика связанная чисто с обработкой данных — и это дело БД, и есть бизнес-логика — и с ней в БД делать нечего.
V> А сейчас просто пройдись по любому XXXDataReader::ReadIn32(), и ужаснись всей этой безразмерной цепочке кода, которая сопровождает чтение каждого поля каждой строки.
Ну, допустим, System.Data безбожно кривой. Мой поинт в том, что надо лечить System.Data, а не засовывать все в один процесс.
V>Нет, браузер как пример, а тормозит он толи из-за множественных запросов на одну страницу, то ли от природы формирования современных php/jsp/asp страниц, толи еще от чего — не суть, когда гуй не браузерный, то пользователь ожидает адекватную реакцию.
Так, ты считаешь, что сейчас проблемы сделать нормальную реакцию на UI в распределенном приложении и они решатся, если прикладной код будет исполняться в одном процессе с БД?
Здравствуйте, VladD2, Вы писали:
VD>А что вызывает геморрой? Если, можно по конкретнее.
Геморрой вызывает отладка, сопровождение, тестирование и развертывание. Начиная от того, что сборки надо регистрировать в сиквеле, и заканчивая тем, что ДБА и разработчики дотнетного кода — несколько разные люди, хорошо квалифицированные в своей области, но имеющие довольно слабые представления о другой.
Моя последняя попытка использовать это на практике воспитала во мне очень серьезный скепсис к подобного рода решениям.
VD>А причем тут бинарная сериализация дотнета? Если ты из сервера приложений используешь запросы к сиквелу, то пользуешся его форматом стрима который очень эффективен.
Я имел ввиду способ связи с сервером приложений; разумеется, формат данных SQL-сервера гораздо эффективнее, т.е. о том и речь, что эффективнее напрямую к SQL подключаться не только из-за отсутствия лишней прослойки, но так же из-за формата данных. Есть, конечно, еще более эффективные форматы данных — это CORBA или даже ASN.1, но они требуют дополнительной спецификации интерфейса.
V>>Насчёт "улучшать способ взаимодействия", дык и этим занимался однажды, перелопачивая на ручную сериализацию, где те самые 50 раз в выигрыше и ...Старые добрые OLE DB интерфейсы кажутся гораздо более продуманными в плане эффективного манипулирования данными, чем предложенный System.Data и далее в глубь по нейспейсам.
VD>Ты меня извини. Я теоретически с тобой за одно, в том смысле, что тоже считаю, что сервер приложений встроенный в СБУД — это хорошая идея. Но то что ты говоришь — это мягко говоря заблуждения. Причем тут System.Data?
VD>IDataReader самый эффективный способ чтения данных из MS SQL из имеющихся в природе. Никакие OLE DB провайдеры и рядом не валялись.
Нет, это не так. И я имею ввиду не классическое ADO над OLE DB, и тем паче не ADO.Net OLE DB provider, именно сами OLE DB интерфейсы, которые весьма и весьма продуманны для целей эффективного взаимодействия. Показательно то, что в начале OLE DB провайдеры для многих баз делали как обертки над ODBC, но затем, "проникнувшись" стали поступать ровно наоборот.
Согласен лишь с тем, что, написав парсер стрима MS SQL прямо в дотнет, они немного выиграли. Но никто не предоставил такого сценария работы, когда валидирование типов колонок производится лишь однажды, и затем результат парсинга непосредственно куда-то льётся без тонны проверок на каждом поле. Для подобного сценария помогло бы нечто вроде инверсии, наподобии DabaAdapter.FillTable(table), только нужен типизированный вариант, а не тупое GetValues(object[] values) на каждую строчку.
Сегодня ситуация такова, что затраты на приседания вокруг извлечения готового значения поля данных чуть ли не на порядок выше, чем затраты парсера стрима SQL на его разбор.
V>>--------- V>>И просто поверь, когда GUI откликается практически мгновенно, или тормозит секунду-другую, как в браузере, это ОЧЕНЬ большая разница. Привыкнув к первому, с трудом подавляешь раздражение, работая со вторым.
VD>Кому нужна вера? Есть методы исследования, измерения, тесты...
Есть много чего. Если ты собрался субъективные ощущения переводить в цифры, то я могу дать ориентировочные отправные данные — это примерно 0.5 сек для субъективно "быстрого" отклика GUI, выше примерно 1.5 сек начинает уже раздражать.
Ты вообще видел хоть раз, как девочки накладные настукивают в сотни (иногда до пары тысяч) строк?
VD>Создай примитивный тест или просто почитай статьи с этого сайта. В них такие тесты уже делались. Причем много лет назад.
Здравствуйте, IB, Вы писали:
V>>Гхм, вообще-то абзацем выше уже был контекст про сервер приложений, так что весь этот абзац к нему и относился. А пихать WCF туда, где 90% банального stateless CRUD, т.е. "прослойка" практически без самостоятельного функционала — это перебор, ИМХО. Такая прослойка должна быть как можно тоньше. IB>Это ты просто WCF не видел, наверное.. =) При желании — тоньше не придумаешь, не вижу никаких проблем запихнуть его всюду, где хоть какая-то передача данных, особенно тупой CRUD.
Как может XML быть тоньше того же ASN.1, например? (формат стрима от MS SQL близок по духу)
Я может, скажу громко, но использование СУБД настолько широко сейчас, что ко многим сценариям обобщённое требование звучит как "реалтайм". Дык, надо от туда и брать наработки.
V>> а бывшие аппологеты максимально-внутри СУБД-ориентированной обработки данных уже начинают советовать WCF по каждому чиху. IB>Если это на меня намек, то я всегда был апологетом здравого смысла.. И был одинаково против как всего пихания в базу, так и выпихивания всего из базы. Есть логика связанная чисто с обработкой данных — и это дело БД, и есть бизнес-логика — и с ней в БД делать нечего.
Есть мнение, что эта граница весьма нечёткая, а по мне — так её нет в принципе, ну разве что выбираемыми абстракциями мы можем лишь условно её проводить. Для своего успокоения, ну типа всё у нас декомпозированно по последнему слову техники: там персисент, а там БЛ.
Ну смешно, право, считать, что вычисляемый столбец в каком-либо запросе — это далеко от бизнес-логики... я уже молчу об агрегатах.
IB>Ну, допустим, System.Data безбожно кривой. Мой поинт в том, что надо лечить System.Data, а не засовывать все в один процесс.
... IB>Так, ты считаешь, что сейчас проблемы сделать нормальную реакцию на UI в распределенном приложении и они решатся, если прикладной код будет исполняться в одном процессе с БД?
Нет, конечно, тут нужен комплекс мер. Просто реализация "бизнес-логики" в виде sored procecure решает сразу два пункта из этого комплекса: убирает 2 лишние сериализации (заметь — самые неэффективные из всей цепочки), а так же лишний слой межпроцессного взаимодействия (который на современных ОС не эффективен по фундаментальным причинам).
Согласись, что СУБД изначально стали выносить за пределы приложений с целью обеспечения безопасности данных путём такого изолирования. Управляемые среды с валидируемым кодом, ИМХО, решают эту проблему. Сейчас связь с этими stored proc на .Net не самая эффективная, на основе "того что было" (System.Data), если народ будет этим повсеместно пользоваться, то возникнет требование более легковесного и типизированного решения, которое вполне может быть реализовано MS.
Меня как 1С ника интересует такой тест использования хранимых процедур на Net.
Часто в модулях проведения приходится использовать рекурсивные алгоритмы, и разветвленные алгоритмы, где иногда нужно добираться доатрибута через 4-5 точку, где каждый новый шаг зависит от предыдущего. (10 тысяц строчек кода не предел).
Такие вещи перекрасно проходят для локальных баз (файловый кэш прекрасно работает со всеми процессами напримерв терминалах, но ужасно долго в SQL).
Вот можно какой нибудь тест на проход по таблице с доступом по ссылочным полям по 2 3 из исходной таблцы с джойнами с иерархией в хотя бы в 3 таблицы.
Интерес насколько тормозит межпроцессное взаимодействие.
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, vdimas, Вы писали:
V>Как может XML быть тоньше того же ASN.1, например?
А ему не надо быть тоньше, он и так достаточно тонок. По факту, межпроцессное взаимодействие с помощю WCF проигрывает DCOM-у на пренебрежимо малую для подавляющего большинства реальных приложений величину.
V>Я может, скажу громко, но использование СУБД настолько широко сейчас, что ко многим сценариям обобщённое требование звучит как "реалтайм". Дык, надо от туда и брать наработки.
Зачем, если и так не плохо все работает. Ну не самое это узкое место.
V>Нет, конечно, тут нужен комплекс мер. Просто реализация "бизнес-логики" в виде sored procecure решает сразу два пункта из этого комплекса: убирает 2 лишние сериализации (заметь — самые неэффективные из всей цепочки), а так же лишний слой межпроцессного взаимодействия (который на современных ОС не эффективен по фундаментальным причинам).
Проблема только в одном, эти две неэффективные сериализации и прочие взаимодействия — отнюдь не самые узкие места во всей цепочке. И вынесение всего барахла на сиквел, только прибавит проблем с поддержкой и разработкой, а вот скорости практически не увеличит.
V>Согласись, что СУБД изначально стали выносить за пределы приложений с целью обеспечения безопасности данных путём такого изолирования.
Не безопасности, а масштабирования. СУБД, как персистенс хранилище не масштабируется вообще, стейтлес же логику можно размазать по произвольному количеству серверов, получая практически линейную масштабируемость.
А вот безопасность как раз проще держать в БД.
V>Управляемые среды с валидируемым кодом, ИМХО, решают эту проблему. Сейчас связь с этими stored proc на .Net не самая эффективная, на основе "того что было" (System.Data), если народ будет этим повсеместно пользоваться, то возникнет требование более легковесного и типизированного решения, которое вполне может быть реализовано MS.
Я вполне доволен тем, что из себя представляет System.Data сейчас, и не вижу никаких причин помещать логику в БД. Никаких практических проблем это не решит, а лишней возни здорово прибавит.
Здравствуйте, IB, Вы писали:
IB>Здравствуйте, vdimas, Вы писали:
V>>Как может XML быть тоньше того же ASN.1, например? IB>А ему не надо быть тоньше, он и так достаточно тонок. По факту, межпроцессное взаимодействие с помощю WCF проигрывает DCOM-у на пренебрежимо малую для подавляющего большинства реальных приложений величину.
Это от того, что тяжеловесная XML сериализация занимает не самое большую долю тиков в межпроцессном взаимодействии, ЧТД.
V>>Я может, скажу громко, но использование СУБД настолько широко сейчас, что ко многим сценариям обобщённое требование звучит как "реалтайм". Дык, надо от туда и брать наработки. IB>Зачем, если и так не плохо все работает. Ну не самое это узкое место.
А какое же место тогда узкое?
Популярные нагрузочные сценарии — это, например, онлайн магазины или распределённые системы для формирования заказов у оптовых фирм. Или системы реалтайм обработки котировки ценных бумаг. В этих базах исторические данные обычно отделены от оперативных. Сценарии оперативного плана дергают не более десятка основных справочников/регистров, в которых порядка единиц-десятков тысяч записей (большинство остальных справочников — это всякие классификационные в десятки и сотни записей, т.е. вообще семечки), и единицы таблиц движений, в которых данные попадают относительно редко — при свершении транзакции (в смысле сделки, а не в смысле атомарной операции СУБД). В разогретом состоянии такая база отвечает действительно "мгновенно", не являясь узким местом. И все эти пляски апп-серверов вокруг базы, да еще на столь расточительных технологиях, добавляют задержку, сопоставимую с полезной или даже большую. Сей факт неприятен сам по себе, не находишь?
Здравствуйте, vdimas, Вы писали:
V>Это от того, что тяжеловесная XML сериализация занимает не самое большую долю тиков в межпроцессном взаимодействии, ЧТД.
С чего бы ей быть тяжеловесной-то?
V>А какое же место тогда узкое?
БД запросы и взаимодействие с удаленным клиентом.
V> В разогретом состоянии такая база отвечает действительно "мгновенно", не являясь узким местом.
Это "мгновенно", все равно больше, чем сериализация/десериализация и межпроцессное взаимодействие.
V> И все эти пляски апп-серверов вокруг базы, да еще на столь расточительных технологиях, добавляют задержку, сопоставимую с полезной или даже большую. V>Сей факт неприятен сам по себе, не находишь?
Не нахожу.. Я не нахожу, что технологии расточительные, я не нахожу, что они добавляют сопоставимую задержку (в тех случаях где имеет смысл сопоставлять) и, как следствие, я не нахожу в этом неприятных фактов.
Но дело даже не в этом, а в том, что даже если это и проблема, то решаться она должна уж ни как не внесением стейтлес логики в базу.
Здравствуйте, IB, Вы писали:
IB>СУБД, как персистенс хранилище не масштабируется вообще, стейтлес же логику можно размазать по произвольному количеству серверов, получая практически линейную масштабируемость.
Позвольте, это как же персистенс хранилище не масштабируется? Вот к примеру:
Scale up:
— Больше винчестеров
— RAID
— Меняем физ. интерфейс к HDD, например используем RAM
Scale out:
— DB cluster
— Distributed File System (та же MogileFS к примеру)
Повреждение мозга после ректальной биопсии — редкая штука (с) Хаус
Здравствуйте, server_mouse, Вы писали:
_>Позвольте, это как же персистенс хранилище не масштабируется?
А вот так. Речь о том, что производительность стейтлес решений можно поднять просто поставив больше железок вокруг (горизонтально), масштабировать же стейтфул толком можно лишь увеличивая мощность одной железки, что сильно снижает перспективы такого масштабирования.
_>Вот к примеру: _>Scale up: _>- Больше винчестеров _>- RAID
... _>- Distributed File System (та же MogileFS к примеру)
Количество доступного дискового пространства на производительность влияет мало.
_>- Меняем физ. интерфейс к HDD, например используем RAM
Про ACID забудь в этом случае и это все опять про одну железку.
_>Scale out: _>- DB cluster
Посмотри на tpc.org — там очень наглядно показано, как одна мощная железка рвет на тряпки любой кластер, перекрывая его в производительности в несколько раз. В последнее время там помоему вообще забили на попытки собрать производительный OLTP кластер.
Здравствуйте, IB, Вы писали:
_>>- Больше винчестеров _>>- RAID IB>... _>>- Distributed File System (та же MogileFS к примеру) IB>Количество доступного дискового пространства на производительность влияет мало.
В производительности можно выйграть, если, к примеру, поместить разные БД на разные физические диски.
Не все RAID одинаково полезны. Для перфоманса есть к примеру RAID0, RAID3.
По поводу distributed FS тоже зря — нагрузка так же распределяется. Узким местом становится сетевое взаимодествие, но и это решается применением того же оптоволокна.
_>>- Меняем физ. интерфейс к HDD, например используем RAM IB>Про ACID забудь в этом случае и это все опять про одну железку.
Конечно — это же scale up.
_>>Scale out: _>>- DB cluster IB>Посмотри на tpc.org — там очень наглядно показано, как одна мощная железка рвет на тряпки любой кластер, перекрывая его в производительности в несколько раз. В последнее время там помоему вообще забили на попытки собрать производительный OLTP кластер.
Ну тут конечно трудно спорить. Проблемма в том, что у железки есть чёткий потолок, а кластер можно наращивать постепенно, что-то оптимизируя "по ходу пьесы". В итоге — большая гибкость. Пройдёт 2 года и ваша железка морально устареет, в то время как ваш конкурент будет неспеша апгрейдить кластер.
Повреждение мозга после ректальной биопсии — редкая штука (с) Хаус
Здравствуйте, server_mouse, Вы писали:
_>Пройдёт 2 года и ваша железка морально устареет, в то время как ваш конкурент будет неспеша апгрейдить кластер.
Так это решение совсем другой проблемы, проблемы неспешного апгрейда.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IB, Вы писали:
_>>>- Больше винчестеров _>>>- RAID IB>>... _>>>- Distributed File System (та же MogileFS к примеру) IB>>Количество доступного дискового пространства на производительность влияет мало. _>В производительности можно выйграть, если, к примеру, поместить разные БД на разные физические диски. _>Не все RAID одинаково полезны. Для перфоманса есть к примеру RAID0, RAID3. _>По поводу distributed FS тоже зря — нагрузка так же распределяется. Узким местом становится сетевое взаимодествие, но и это решается применением того же оптоволокна.
_>>>- Меняем физ. интерфейс к HDD, например используем RAM IB>>Про ACID забудь в этом случае и это все опять про одну железку. _>Конечно — это же scale up.
_>>>Scale out: _>>>- DB cluster IB>>Посмотри на tpc.org — там очень наглядно показано, как одна мощная железка рвет на тряпки любой кластер, перекрывая его в производительности в несколько раз. В последнее время там помоему вообще забили на попытки собрать производительный OLTP кластер. _>Ну тут конечно трудно спорить. Проблемма в том, что у железки есть чёткий потолок, а кластер можно наращивать постепенно, что-то оптимизируя "по ходу пьесы". В итоге — большая гибкость. Пройдёт 2 года и ваша железка морально устареет, в то время как ваш конкурент будет неспеша апгрейдить кластер.
Класный пример кстати — ЖЖ. Видели их презенташку? Вместо того, что бы купить "крутую железку", поставить на неё базу и радоваться пока не упрёшься в потолок, они крутили кластер. Причём в разных вариациях, каждый раз анализируя распределение нагрузки и узкие места. В итоге пришли решению где одна база разбита на кучу маленьких — благо логика приложения позволяла. Очень поучительно имхо.
Повреждение мозга после ректальной биопсии — редкая штука (с) Хаус
Здравствуйте, server_mouse, Вы писали:
_>Класный пример кстати — ЖЖ. Видели их презенташку? Вместо того, что бы купить "крутую железку", поставить на неё базу и радоваться пока не упрёшься в потолок, они крутили кластер. Причём в разных вариациях, каждый раз анализируя распределение нагрузки и узкие места. В итоге пришли решению где одна база разбита на кучу маленьких — благо логика приложения позволяла. Очень поучительно имхо.
Поучительно здесь прежде всего то, что логика приложения позволяет разбить базу на кучу маленьких. Случай мягко говоря редкий в ентерпрайзах. Чаще получается разбивать базу на логически независимые блоки, немного пожертвовав целостностью.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, server_mouse, Вы писали:
_>>Класный пример кстати — ЖЖ. Видели их презенташку? Вместо того, что бы купить "крутую железку", поставить на неё базу и радоваться пока не упрёшься в потолок, они крутили кластер. Причём в разных вариациях, каждый раз анализируя распределение нагрузки и узкие места. В итоге пришли решению где одна база разбита на кучу маленьких — благо логика приложения позволяла. Очень поучительно имхо.
IT>Поучительно здесь прежде всего то, что логика приложения позволяет разбить базу на кучу маленьких. Случай мягко говоря редкий в ентерпрайзах. Чаще получается разбивать базу на логически независимые блоки, немного пожертвовав целостностью.
К тому и веду — persistence вполне себе масштабируется, просто нужно знать как готовить. Хоть и не без гемороя.
Повреждение мозга после ректальной биопсии — редкая штука (с) Хаус
Здравствуйте, server_mouse, Вы писали:
_>В производительности можно выйграть, если, к примеру, поместить разные БД на разные физические диски.
Это все не про то, это по прежнему одна железка и далеко не все базы позволяют размазать нагрузку по дискам.
_>Конечно — это же scale up.
Те кто могут себе такое позволить — ставять MySQL и не парятся.
_>Ну тут конечно трудно спорить.
Об чем и речь.
Здравствуйте, server_mouse, Вы писали:
_>Класный пример кстати — ЖЖ. Видели их презенташку?
ЖЖ, кстати пример не очень классный, но речь не о нем...
_>Вместо того, что бы купить "крутую железку", поставить на неё базу и радоваться пока не упрёшься в потолок, они крутили кластер. Причём в разных вариациях, каждый раз анализируя распределение нагрузки и узкие места. В итоге пришли решению где одна база разбита на кучу маленьких — благо логика приложения позволяла. Очень поучительно имхо.
Вот и я о том же. Далеко не все приложения можно таким образом размазать по нескольким узлам. И выходом тут является вынесение на эти узлы стейтлес логики, причем этот способ относительно универсальный, который работает везде, где есть эта стейтлес логика. Ровно по этой причине мне и не нравится запихивание этой стейтлес логики в БД, что убъет идею вынесения ее на другие узлы.
Здравствуйте, server_mouse, Вы писали:
_>К тому и веду — persistence вполне себе масштабируется, просто нужно знать как готовить. Хоть и не без гемороя.
Как бы так тебе объяснить.. =) Здесь, в принципе, все примерно представляют, включая интимные подробности, как именно масштабируется БД и какими ритуальными приседаниями это делается. Речь о том, что горизонтально отмасштабировать стейтлес напорядок легче. И по сравнению с этим БД таки нефига не масштабируется (хотя мы все прекрасно знаем как это делается).
Здравствуйте, server_mouse, Вы писали:
IT>>Поучительно здесь прежде всего то, что логика приложения позволяет разбить базу на кучу маленьких. Случай мягко говоря редкий в ентерпрайзах. Чаще получается разбивать базу на логически независимые блоки, немного пожертвовав целостностью.
_>К тому и веду — persistence вполне себе масштабируется, просто нужно знать как готовить. Хоть и не без гемороя.
Не всегда масштабируется, а когда масштабируется, то бывает, что не вполне достаточно. В любом случае, нужно использовать все доступные средства, и первые, и вторые, а не отмахиваться от первых только потому, что есть вторые.
Если нам не помогут, то мы тоже никого не пощадим.