|
|
-
Думаю уже всі встигли встигли прочитати новину про новий айтішний портал і протестити його функціонал, тому "копіпастити" в свій блог цю інформацію не буду. Якщо ще не встигли - "лінки вам в руки" :) Особисто від себе додам: все сподобалось! Як ідея, так і реалізація. Розробникам бажаю продовжувати розвивати ресурс з тим же ентузіазмом! Тепер коротко про те для чого я почав писати цей пост :) Коли прочитав "Файловое хранилище SkyDrive" аж в голові закрутилось :) Памятаю, читав що команда SkyDriv-a хотіла випустити API, але новин про реліз так і не було... а тут цілий ПОРТАЛ зберігає файли на майкрософтських серверах! ХАЛЯВНО! 5 Гігабайт! На жаль, після біглого перегляду коду вияснилось, що ніякого API портал не використовує... Натомість девелопери ( Константин Косинский і Алена Косинская) цілком успішно використали уже наявні можливості (дивимось VideoListControl.ascx): </asp:XmlDataSource ID="fileListDataSource" runat="server" DataFile="<%$ AppSettings:FileList %>" XPath="/rss/channel/item" EnableCaching="true">Ключ "FileList" веде сюди.Залишилось придумати якби реалізувати автоматичне додавання файлів і можна запускати власний rapidshare :)
|
-
На днях менеджерам моєї компанії захотілось чогось "великого і прекрасного", ну як завжди  Коротка суть "великої" ідеї: юзер аплоадить файл на сервер, який потім треба певним чином обробляти. Ніби нічого незвичайного... окрім того, що всі юзери "по дефолту" - погані і можуть загрузити якусь "бяку"  Під останнім розуміються дві речі: "небажаний контент" (порнографічні/расистські малюнки, ...) і віруси. На жаль, з першим можна боротись тільки людськими ресурсами... а от другий треба фільтрувати автоматично на етапі аплоаду. Не знаю хто як звик відловлювати віруси у себе на компі, але я довіряю свій дорогоцінний лептоп антивірусу AVG :) Майже так само думає і керівництво моєї компанії і для того щоб гарантувати "тотал секюріті" придбало N ліцензії Касперського (з таким вибором я не зовсім згідний, але моєї думки ніхто не питався). Думаю, всім зрозуміло що сканувати кожен файл що був завантажений на сервер вручну - це повний ідіотизм (тим більше, якщо в словниковому запасі є такі страшні слова як "Касперський" і "API"  ) Після недовгих пошуків в Гуглі я знаходжу сторінку з описом Kaspersky Antivirus SDK... і НЕ знаходжу лінка на скачування цього SDK! Перше що подумалось - сьогодні не мій день! Але не все так погано і завжди можна мило поспілкуватись з саппортами :) Дзвоню... спілкуюсь... І що цікавого я дізнався? Перше, музика "на очікуванні" у них досить непогана, хоча постійно повторюється  (я це перевірив за ті 4 рази як дзвонив, в сумі "провисів" на ліній чуть більше пів години). Друге, саппорт уявлення не має що таке SDK і головне що існує Kaspersky Antivirus SDK (я не став їх шокувати історіями про інші SDK, які описані у них на сайті :) )! Третє, на російському сайті касперського про SDK нічого не згадується! (в кого є думки з цього приводу - прошу прокоментувати). В результаті, все що я отримав - це мейл саппорту SDK. (в цьому місці мій настрій суттєво покращився і я навіть вирішив, що сьогодні мені щастить, але...) Пишу лист в SDK-саппорт: доброго-дня-бла_бла_бла-треба-SDK-підкажіть-де-скачати. На моє щастя відповіли мені досить швидко, десь за 3-3.5 години, але замість довгоочікуваного лінка ввічливо поцікавились для чого він мені здався. Ну що ж, в скороченій формі пояснюю хто я, в якій компанії працюю і для чого мені потрібен SDK. Пройшло ще 3 години... Отримую ще одну відповідь... скажу чесно, я очікував будь що: від "а SDK можна скачувати тільки на Новий Рік і Піздво"  до "ми забули видалити наш першоквітневий жарт", але аж ніяк не "Я передам ваші контактні дані нашим менеджерам і вони з вами звяжуться"! При цьому варто зауважити, що спілкувався я не з простим девелопером, а з одним із керівників (принаймні в підписі мейлів у нього значиться такий статус)! За своє життя мені довелось скачати немало SDK-шок, але ще ні разу для цього не треба було витрачати стільки часу на спілкування з саппортами і тим більше розмовляти з менеджерами (в принципі, це мене чекає в найближчому майбутньому). Я взагалі мовчу про логічне питання "а для чого це все?". Таке враження, що керівництво компанії всіма силами старається запобігти інтеграції своїх продуктів з іншими системами (хоча в цьому випадку можна було б взагалі не згадувати про SDK). А відповідальні керівники бояться приймати хоча б якісь відповідальні(?) рішення... Повний "ахтунг"! І для чого я це все написав..? Головна мета посту - надати першу інформацію тим нещасним, хто захоче повторити мій шлях. Ну і запитати в шановних колег якщо хтось уже мав незабутній досвід спілкування з менеджерами/девелоперами Касперського - відпишіться, пліз, в коментах! Буду дуже вдячний за будь-яку інформацію UPDATE 13.08.2008На наступний день після написання цього поста мені написав sales-менеджер Касперського (тут можна поставити 5+ за оперативність!). Він переслав документ який треба було підписати і відіслати назад, коротка суть документу - моя компанія не має права копіювати/продавати і т.д. Kaspersky AntiVirus SDK ну і т.д. Як результат, після узгодження всіх формальностей, я мав би отримати демо версію SDK. Так як пересилання мейлів/факсів ніколи не було моєю сильною стороною, я просто подзвонив sales-менеджеру і поцікавився скільки коштує повна версія AntiVirus SDK. На мій подив, він не зміг дати мені навіть приблизну відповідь (wtf?!). Основним аргументом неможливості сказати ціну було те, що вони не знають які зміни в SDK мають бути зроблені спеціально на моє замовлення (я так і не зрозумів чи вони для всіх "підганяють" пакет, чи це тільки я попав на спец. акцію :) ). Хоча я і був трохи шокований таким розвитком подій, але все-таки поцікавився скільки ж буде коштувати "стандартний" пакет... на що мене ввічливо запитали "а скільки користувачів буде перевіряти ваша система?". Скажу чесно, таке питання повністю відправило мене в нокдаун! Можна було б зрозуміти питання "а скільки серверів з нашим антивірусом ви маєте і на скільки з них буде залучено у вашому проекті?", але кількість користувачів - це повний "ахтунг"! Закінчивши розмову, я переслав лист з документом проджект менеджеру і попросив його розібратись в ситуації. До цього часу, ніяких новин від мого ПМ-а на рахунок Kaspersly SDK не надходило (я так підозрюю що і не надійде). P.S.: може хто знає, чи існує ще вітчизняний антивірус UNA? памятаю, колись про нього досить непогано відзивались і я навіть хотів купити ліцензуйну версію, але так і не зміг її знайти :(
|
-
Не знаю хто як переклав "Meshed" і про що подумав, але мова зараз піде про платформу LiveMesh  Про LiveMesh я встиг начитатись всяких маркетингових "охів-ахів" і навіть зареєструвався в черзі на тестування... але 2 дні тому фортуна показала свою начищену до блиску "блендаметову" посмішу і завдяки добрим людям у мою Гмейловську скриньку "впало" запрошення на тестування "LiveMesh tech preview" :) Скажу чесно, після залогінювання на порталі я спочатку було витягнув свій губозакатувальний механізм і почав шукати якусь лінку з текстом "Download LiveMesh SDK" (що цілкому природньо для девелопера  )... але круто обламався  Простим смертним треба чекати осіннього публічного релізу (тоді як деякі словочі програмери уже використовують SDK "на повну" і успішно викладають скрінкасти на цю тему!). Як тільки стало зрозуміло, що SDK мені не знайти, я почав освоюватись в користувацькому веб-інтерфейсі... Що тут можна сказати? Виглядає досить симпатично :) Звичний віндовський інтерфейс стилізований під Vist-у:  Але це тільки мала частина всіх можливостей! Щоб відчути що таке LiveMesh насправді, потрібно додати свій ПК в "девайси" і визначити папки які будуть синхронізуватись:
При додаванні ци самих девайсів не обійшлось без "ложки дьогтю"  Мій робочий ПК працює під ОС WinServer 2003, яка не входить у список ОС що підтримуються клієнтом LiveMesh (він є частиною процесу додавання нового девайсу і він же потім синхронізує папки/файли з сервером), тому він вперто показував ось таке симпатичне вікно:  Після недовгих пошуків виявилось, що проблему вирішує параметр "-Force" при запуску інсталяційного пакету  Чому було просто не додати на форму кнопку "Install anyway" для мене так і залишилось загадкою. Після інсталяції і додавання свого робочого ПК в список девайсів клієнт працював стабільно, ніяких проблем помічено не було... Дивно, правда?  І так, синхронізувати файли між ПК і сервером - це круто... але якось тупо  Процес дуже скидається на банальний бекап. Тому було вирішено принести в жертву домашній лептоп і встановити LiveMesh клієнт ще й на нього. І тут [цензура] знову "лажа"!!! Клієнт навідріз відмовився інсталюватись на Win XP SP2 :( Знову до болю знайоме "-Force"... знову все працює ОК  Наступним пунктом в списку тестування стояло "розшарювання" папки... На цьому етапі не було ніяких сюрпризів, все пройшло без проблем. Тепер коротке резюме: у мене є 2 ПК з встановленим LiveMesh клієнтом, розшарена папка і велике бажання щось поламати :)) Останнє вилилось у тестування функції "Live Remote Desktop" (яка, як сказано в маркетингових матеріалах, має працювати стабільно незважаючи на фаєрволи, NAT та інші страшні слова :) ). Для тестування "живого" RD я спершу законектився з робочого ПК на домашній лептоп. В загальному - враження позитивні, хоча відчувались невеликі затримки, яких ніколи не було при використанні звичного Remote Desktop. Окрім цього, попри всі нові корисні "features", які мають гарантувати ще більшу безпеку зєднання, я був радий побачити що копіювання файлів між 2 ПК через Remote Desktop працює і надалі :) Але кому воно потрібне, якщо у нас є папка з автоматичним синхронізуванням.?! Зізнатись чесно, до питання синхронізації файлів я підійшов з особливим ентузіазмом! Скопіювати 1-2 фільми було б найпростіше (в мому тестовому аккаунті доступно 5 Гб), але користі від них мало... тому я скопіював "trunk" SVN-a проекту CC.NET :) Процес синхронізації "лептоп -> LiveMesh Server -> робочий ПК" зайняв біля 5-10 хв (70 Мб). Результат доволі непоганий, АЛЕ як завжди не все так добре як здається. На даний момент у LiveMesh не реалізовано функції " diff", тому при зміні файлу клієнт синхронізує його ПОВНІСТЮ, що доволі неекономно з точки зору трафіку (для прикладу, в цьому проекті завдяки diff-у все працює набагато швидше). На додаток, при синхронізації кудись пропали всі "hidden" папки (у мому випадку це були всі ".svn"-папки). Після випробування функції "Live Remote Desktop" з робочого ПК підійшла черга до лептопа. У цьому місці треба зробити невеликий відступ і сказати, що робочі ПК в моїй компанії "заховані" за 2 чи 3 фаєрволами і ще якоюсь фігньою, яку я не зовсім розумію... Тому для забезпечення конекту своїх працівників до робочого місця компанія використовує софт третьої сторони, що створює тимчасовий VPN канал між робочим і домашнім ПК. На даний момент це єдиний спосіб доступу ззовні. Знову звичний інтерфейс клієнтської програми...  Connect to device... УРА! я знову можу читати свою робочу пошту :) Хоча останнє трохи проблематично робити і ось чому саме: на роботі у мене два 21-дюймових монітори (Dual Monitor), в кожного з них "Screen resolution" більший ніж на мому лептопі... і тепер уявіть собі картину, коли цей Extended Desktop пробує втиснутись на маленькому (15.4 дюйми) лептопному дисплеї... уявили? Картина явно не для людей з слабкою психікою! Раніше, при використанні звичайного Remote Desktop-а, все працювало нормально: Screen resolution на робочому ПК змінювався, вікна з додаткового монітору "зїжали" на основний, що давало можливість нормально працювати... А зараз "хотіли зробити як краще, а получилось як завжди" :( Сподіваюсь, у фінальній версії все буде працювати як і має працювати :)
Summary. Що тут можна сказати? 1) Як для "tech preview" версії все працює досить непогано, будемо надіятись, що надалі все буде тільки краще :) 2) В процесі роботи я все-таки побачив одне вікно помилки... нажаль все що там було написано це "Виникла помилка (а я і не помітив :) ). Номер помилки такий_то". Не знаю як хто, а я б хотів побачити більш інформативний текст :) Хоча це ще можна списати на версію продукту... 3) Також хочеться думати, що в майбутньому Майкрософт перестане дразнитись скрінкастами на тему "як буде добре жити коли ми випустимо SDK" без надання можливості попробувати це SDK!
Особисто від себе хочу додати: ЗОДОВБАЛО вікно допомоги! Я так і не знайшов спосіб, щоб його відключити :(
Всім дякую за увагу :) Також буду радий почути про ваш досвід роботи з LiveMesh!
|
-
З самого початку думав почати цей пост з слів типу "який я хороший, добрий, мудрий і т.д."... але прийдеться визнати, що я ППЦ який лінивий :)) Як усім уже, мабудь, відомо Microsoft 23 травня цього року виклала в публічний доступ свій Source Analyzer (StyleCop). І все було б просто супер, якщо б не той факт, що всі правила перевірки коду - абсолютно статичні :( Щоб остаточно переконатись в цьому, в день релізу я трохи "погуглив" і натикнувся на цікавий пост, де один з кодерів майкрософта розказував які вони щасливі з своїм Source Analyzer-ом :) Також він писав, що правила у ньому статичні не через "криві руки "... а тому що тільки ці правила можуть принести абсолютне щастя девелоперам які будуть ними керуватись! Одним словом, логіка в його словах проста - "ми щасливі, і вам прийдеться бути щасливими" :) Так як характер у мене поганий, я погано сприймаю той факт що комусь роблять добре. Тому з допомогою Reflector-а я дизасемблював Source Analyzer і хотів створити свої правила. Проте, все що було після дизасемблювання йшло туго і постійно відкладувалось "на завтра" :( Як результат - фінішна пряма позаду, але перше місце дісталось іншому. Цього "іншого" і його статтю можна знайти тут. Що я можу сказати..? В пості добре описаний шлях створення custom rules з прикладами, всі хто хотів додати в StyleCop щось своє тепер мають таку можливість :) Думаю, в найближчому майбутньому можна сподіватись на появу Add-In-а
який дозволить писати власні правила в конфігураційних файлах і
створювати локальне (проте власне!) щастя :) P.S.: Також раджу зайти сюди. Автор цього поста пробує схрестити StyleCop з ReSharper-ом! І навіть пообіцяв викласти сорси в публічний доступ!
|
-
Не так давно
Mike Chaliy опублікував пост про перевірку параметрів за допомогою Rhino.Mocks. Так як мені довелось трохи попрацювати з TypeMock.NET, то я поцікавився у автора чи не знає він як реалізувати подібну штуку там. Нажаль Mike Chaliy дав негативну відповідь :( тому прийшлось розбиратись самотужки. В результаті виявилось, що у TypeMock.NET це реалізовується набагато простіше: public class SomeClass { public int TestMethod(int x, string y) { throw new NotImplementedException("TestMethod(int, string) is not implemented"); } } [TestFixture] [ClearMocks] public class Tests { [Test] [VerifyMocks] public void FirstTest() { SomeClass s = new SomeClass(); using (RecordExpectations recorder = RecorderManager.StartRecording()) { recorder.ExpectAndReturn(s.TestMethod(1, "2"), 10).RepeatAlways(); recorder.CheckArguments(Check.Not(-1, "'x'-parameter can't be less than 'zero'"), Check.NotNull("'y'-parameter can't be null")); } Assert.AreEqual(10, s.TestMethod(1, "2")); Assert.AreEqual(10, s.TestMethod(-1, null)); } }Все ніби і класно, але щось підказує, що має бути "ложка дьогтю"... і імя цій ложці - "ліцензія"! :( Іншими словами, код приведений вище буде працювати тільки після покупки Professional або Enterprise ліцензії. А "бідним" студентам прийдеться користуватись "стандартним" набором можливостей: [TestFixture] public class Tests { [Test] public void SecondTest() { Mock sc = MockManager.MockAll(typeof(SomeClass)); sc.AlwaysReturn("TestMethod", 10).Args(Check.Not(-1, "'x'-parameter can't be less than 'zero'"), Check.NotNull("'y'-parameter can't be null")); SomeClass s = new SomeClass(); Assert.AreEqual(10, s.TestMethod(1, "2")); Assert.AreEqual(10, s.TestMethod(-1, null)); } }>> UPDATEТут мене справедливо "ткнули носом" в той факт, що я пропустив важливе слово "Callback" в кінці теми минулого поста від Mike Chaliy. Зараз я постараюсь виправитись і для повноти картини додам ще один код тесту: [Test] public void ThirdTest() { Mock sc = MockManager.MockAll(typeof(SomeClass)); SomeClass s = new SomeClass(); sc.AlwaysReturn("TestMethod", 10).Args( new ParameterCheckerEx(delegate (ParameterCheckerEventArgs e) { if(((int)e.ArgumentValue) < 0) { e.FailureMessage = "First param can't be less then zero"; return false; } return true; }), new ParameterCheckerEx(delegate (ParameterCheckerEventArgs e) { if (e.ArgumentValue == null) { e.FailureMessage = "Second param can't be null"; return false; } return true; })); Assert.AreEqual(10, s.TestMethod(1, "2")); Assert.AreEqual(10, s.TestMethod(-1, null)); }От тепер справді можна порівнювати :)
|
-
Всім алоха!Warning! Якщо ваші релігійні чи ще_якісь_там погляди не дозволяють користуватись такою чудовою тулзою як Reflector, прохання далі не читати! Так як в основі даного поста буде лежати саме його використання.Думаю, цей пост буде цікавий насамперед новачкам у .NET, тому прохання до "фулів" і "суперіорів" не писати коменти в стилі "ми таке в дитсадку робили".Частина перша: передісторіяНедавно я вирішив додати до однієї з власних програмок трохи гламуру (під "власною" я розумію тулзу, яку використовую виключно я і тільки я). Конкретніше, мені знадобився красивий ListView  Гугл видав декілька результатів, але мій вибір впав саме на цей контрол. І хоча виробник не давав ліцензії "for non-commercial use", я все-одно вирішив викачати бібліотеку і протестувати її тріальну версію  Скачав... проінсталював... переніс контрол на форму... тут мені запропонували або купити контрол, або задовільнитись 30-денним тріальним періодом, я вибрав тріал (у нашому колгоспі поки не дають грошей на такі гламурні штуки  )... додав декілька колонок у ListView... натиснув F5... і тут мені повідомляють: Не знаю як хто, але я розраховував на трохи більший тріал-період Повторний запуск не дав жодних позитивних результатів  Випивши чаю і обдумавши ситуацію, я вирішив що просто так не здамся і все-таки подивлюсь як виглядає скачаний ListView в дії (звичайно ж крякнувши його перед цим  )! Єдине що лякало в цій ситуації - це захист бібліотеки. Я більш ніж упевнений, що люди, які зробили скачаний мною контрол - професіонали своєї справи. І як професіонали вони вирішили скористатись послугами таких же професіоналів з захисту програмних продуктів. Часи коректування ключів реєстру з назвами IsRegistered давно минули, тому мені мало б світити повне фіаско у справі "крякання"... але, як кажуть, "проба грошей не коштує"  Отож, що ми маємо на цей момент? 1) GUI-бібліотека, яка відмовляється працювати гарантовані 30 днів - 1шт. 2) Велике бажання спробувати цю бібліотеку в дії - 1 ВЕЛИКА шт. 3) Автор цього поста, юзверь який прочитав статтю " Reflector for dummies"  - 1 шт. А що нам необхідно? 1) Все вище перелічене (хоча, третій пункт прийдеться замінити  ) 2) Reflector і один чудовий Add-in до ньогоЗовсім випадково весь необхідний набір виявився у мене на вінчестері  Тому я переходжу до наступної частини! Частина друга: темні справиВідкриваємо папку, куди був встановлений наш GUI-компонент і дивимось які там є бібліотеки. У моєму випадку їх 3: 1) LidorSystems.IntegralUI.DLL 2) LidorSystems.IntegralUI.Lists.DLL 3) LidorSystems.IntegralUI.Lists.ListView.dll Судячи з назв, декомпілювати їх прийдеться у перерахованому вище порядку... Відкриваємо Reflector, додаємо потрібні нам ліби і зберігаємо їхні "сорси" на хард-диск  Як зберегти сорси показано на малюнку нижче ( не забудьте встановити скачаний Add-in!):  В результаті маємо отримати 3 незалежні проекти. Наступний крок: створюємо WinForms-проект (для тестування нашого контрола) і додаємо до нього проекти декомпільованих бібліотек. Після цього потрібно не забути поправити референси в кожному з декомпільованих проектів один на одного, так як на даний момент всі референси вказують на бінарники, а нам потрібно щоб вони були "проектними" (project reference).Тепер пробуємо скомпілювати весь наш солюшн... З першого разу може і не вдатись, так як можуть бути незначні помилки в коді, які потрібно буде виправити. Після вдалого компілювання не поспішайте додавати контрол на форму і пити пиво! Памятаєте заради чого я почав писати цей пост? Правильно! заради обходу механізму тріал-періоду  Тому спробуємо додати ListView програмно ( хоча достатньо буде просто створити екземпляр його класу): private void button1_Click(object sender, EventArgs e) { ListView testControl = new ListView(); Controls.Add(testControl); }Запускаємо WinForms-проект і натискаємо на button1... На моніторі має зявитись вікно аналогічне першому малюнку. Ввічливо відмовляємось від купівлі компоненти і отримуємо exception в методі Init() класу LidorSystems.IntegralUI.Lists.ListView. Код, що викликав exception виглядає так:
if (!base.DesignOnly && !this.Intialize(this)) { throw new Exception("Your evaluation has expired"); }Думаю, логічно буде закоментувати цю частину коду  Після цього компонент можна вільно тестувати! А щоб все було взагалі ідеально, видаліть атрибут LicenseProvider(typeof(EncryptedLicenseProvider)) класу ListView.Заключна частинаЯк висновок можу сказати одне, платити гроші за всякі "хитрі" LicenseProvider-и для компонентів не має змісту. Всі вони легко обходяться і не становлять якусь надзвичайну міру захисту :( В найгіршому випадку, прийдеться витратити на пів години більше часу на видалення перевірки ліцензії Памятайте, що використання "крякнутих" пограмних продуктів категорично заборонене! За таке можна "отримати по вухах" :)
|
-
Арігато!Не так давно я зіткнувся з необхідністю програвання музичних файлів у своїй програмі. Пошук в Гуглі видав досить багато результатів, але всі вони зводились до написання врапера над DirectSound (або використання стандартних засобів .NET Framework, які і є тим самим врапером). Мені було абсолютно всерівно над чим там треба писати врапер (головне, щоб це працювало!), тому я швидко скопіпейстив текст класу у свії проект... і круто обломався! Динаміки навіть не пікнули  , а головне помилок при виконанні коду також не виникло. Тобто, все ніби працює, але в той же момент нічого не працює  Подальші пошуки проблеми дали нульовий результат, у всіх все було "тіп-топ". А якщо і не працювало, то тільки тому що хтось погано скопіпейстив код :( Метод "тику" також не приніс потрібного результату. Єдиним позитивним моментом в цій ситуації було те, що це потрібно для моєї власної тулзи, яку ніхто окрім мене не буде використовувати :) Пройшов приблизно місяць і сьогодні моя "звукова" проблема дістала продовження  Зовсім випадково я натикнувся на бібліотеку, що могла відтворювати більшість популярних аудіоформатів (принаймні, автори так написали). Спортивний інтерес взяв гору і я таки вирішив перевірити чи вона спрацює на мому лептопі. Як виявилось - "не спрацює" :( Але ж хіба я з індуського роду, щоб так швидко здаватись? Тому одразу ж вирішив скачати ще кілька ліб... які в результаті так само вперто відмовлялись працювати! Я вже думав було завершити свої блукання в "павутині", коли натрапив ось на цю сторінку. Чесно кажучи, я був налаштований досить скептично щодо цього продукту, так як він використовував той самий DirectSound :( Але "проба грошей не коштує" і можна було спробувати "покулупатись" ще кілька хвилин :) І, О ЧУДО! все запрацювало! без жодних "танців з бубном"! Якщо у когось виникали такі ж проблеми і ви знаєте ЧОМУ САМЕ вони виникали - відпишіться в коментах!
|
-
Якось давніше пощастило прочитати короткий мануал по
правильному поводженню з SqlDataReader.
Лінк зараз не згадаю, тому прийдеться кортко переказати зміст мануалу.
1. Старайтесь якнайменше використовувати ось такий вид
запису: using (IDataReader reader = SPs.TestSelect().GetReader()) { for
(int j = 0; reader.Read(); j++) { toReturn[j] = new TestItem();
toReturn[j].Age = (int)reader["Age"]; toReturn[j].Gender = reader["Gender"]
as string; toReturn[j].ID = (int)reader["ID"]; toReturn[j].Login = reader["LoginName"]
as string; toReturn[j].Name = reader["Name"]
as string; } }
2. Якщо настільки "приперло" написати код схожий на поданий
вище, то модифікуйте його таким чином: using (IDataReader
reader = SPs.TestSelect().GetReader()) { int
ageIndex = reader.GetOrdinal("Age"); int
genderIndex = reader.GetOrdinal("Gender"); int idIndex
= reader.GetOrdinal("ID"); int
loginIndex = reader.GetOrdinal("LoginName"); int
nameIndex = reader.GetOrdinal("Name");
for
(int j = 0; reader.Read(); j++) { toReturn[j] = new TestItem();
toReturn[j].Age = (int)reader[ageIndex]; toReturn[j].Gender = reader[genderIndex] as string; toReturn[j].ID = (int)reader[idIndex]; toReturn[j].Login = reader[loginIndex] as string; toReturn[j].Name = reader[nameIndex] as string; } }
3. А в ідеалі код має бути схожим на: using (IDataReader reader = SPs.TestSelect().GetReader()) { int
ageIndex = reader.GetOrdinal("Age"); int
genderIndex = reader.GetOrdinal("Gender"); int
idIndex = reader.GetOrdinal("ID"); int
loginIndex = reader.GetOrdinal("LoginName"); int
nameIndex = reader.GetOrdinal("Name");
for
(int j = 0; reader.Read(); j++) { toReturn[j] = new TestItem();
toReturn[j].Age = reader.GetInt32(ageIndex); toReturn[j].Gender = reader.GetString(genderIndex); toReturn[j].ID = reader.GetInt32(idIndex); toReturn[j].Login = reader.GetString(loginIndex); toReturn[j].Name = reader.GetString(nameIndex); } }
В прикладах toReturn –
це «TestItem[] toReturn» + ви якимось чином
дізнались правильний розмір масиву :) Результатом роботи методу є цей самий «TestItem[] toReturn»
Перше що кидається в очі, чому 3-й варіант кращий за перші два
– це unboxing при присвоєнні значень елементам масиву toReturn. А чим другий кращий за перший? Як саме третій варіант
відрізняється від перших двох? Про це в мануалі не написали, тому прийшлось
розбиратись самотужки…
Звичайно, можна було б написати в саппорт майкрософта і
запитати у них, але я вирішив, що з Reflector-ом я справлюсь швидше :)
Хто до читав до цього
місця і вирішив, що дана тема йому малоцікава, може далі не читати. Так як далі
буде тільки дизасемблювання стандартних ліб…
Отож, пройдемось по питаннях по
порядку… 1. Чим другий варіант кращий за
перший?
Відкриваємо у рефлекторі клас SqlDataReader і дивимось на тексти
перегруженого оператора «[]». public override object this[string name] { get { return this.GetValue(this.GetOrdinal(name)); } } та
public override object this[int i] { get { return this.GetValue(i); } }
В
першому лістінгу бачимо, що перед
викликом методу «GetValue» (який очевидно повертає потрібне нам значення :) ),
йде виклик «GetOrdinal»… Відмінність ніби і не значна, але здоровий глузд
підказує, що виконувати «GetOrdinal»
лишні 200-300 тис разів не варто :) Тому від цього моменту конструкція типу
reader["SomeKeyName"] перестає
для нас існувати.
2. Як
саме третій варіант відрізняється від перших двох?
Те що
там відсутнє явне приведення типів – це ми бачимо, але що заховано всередині..? Для прикладу препаруємо метод «GetInt32»
public override int GetInt32(int i) { this.ReadColumn(i); return this._data .Int32; }
Звідси
ясно, що нічого не ясно :) Треба копати глибше! Виклик методу «ReadColumn» я опущу і перейду
до «return this._data .Int32». Цікаво, а що ж за поле «_data»?
private SqlBuffer[] _data;
Хм…
Все одно нічого не ясно… Дивимось що таке «SqlBuffer» (весь код постити не буду, просто покажу те що нам
потрібне):
internal sealed class SqlBuffer { // Fields
private bool _isNull; private object _object; private StorageType _type; private Storage _value;
// Methods …
// Properties …
internal object Value { get { if (this.IsNull) { return DBNull.Value; } switch (this._type) { case StorageType.Empty: return DBNull.Value;
case StorageType.Boolean: return this.Boolean;
case StorageType.Byte: return this.Byte;
case StorageType.DateTime: return this.DateTime;
case StorageType.Decimal: return this.Decimal;
case StorageType.Double: return this.Double;
case StorageType.Int16: return this.Int16;
case StorageType.Int32: return this.Int32;
case StorageType.Int64: return this.Int64;
case StorageType.Money: return this.Decimal;
case StorageType.Single: return this.Single;
case StorageType.String: return this.String;
case StorageType.SqlBinary: return this.ByteArray;
case StorageType.SqlCachedBuffer: return ((SqlCachedBuffer) this._object).ToString(); case StorageType.SqlGuid: return this.Guid;
case StorageType.SqlXml: { SqlXml xml = (SqlXml) this._object; return xml.Value; } } return null; } } internal int Int32 { get { this. | |
|