Открой для себя SQLite.
Многие программисты микрософтовской платформы настолько отзомбированы Билом Гейтсом и его бригадой, что когда им требуется уложить тысчонку строчек в однопрограммном режиме - используют используют бесплатный билогейтсовский SQLExpress. Между тем данная прога для многих приложений весьма тяжеловесна и неудобна. Кроме того, она устроена так, чтобы подспудно втягивать и программиста и его работодателя в явный блудняк - в применение в будущем полной версии билогейтсовского SQL сервера за 54 тысячи долларов на процессор.
Понятно, что шайка Билла Гейтса проводит зомбирование программистов с корыстными умыслами, но ведь и программисты не должны быть тупой быдлотной биомассой и должны понимать к чему приведет примение MS SQL Express. Как проявить элементарную солдатскую смекалку и не впадать в явный блудняк c Биллом Гейтсом - у меня на сайте рассказано достаточно много:
- Используем PostgreSQL вместо MS SQL в проектах на NET и ASP.NET.
- Используем MySQL вместо MS SQL в проектах на ASP.NET.
- ADO.NET обвязка для работы с MySQL в ASP.NET.
- Избавляемся от базы стандартных пользователей ASP.NET на MS SQL - пример ASP.NET сайта на MySQL.
- Этюды на ASP.NET. Пример сайта на СУБД PostgreSQL.
- Поднимаем на хостинге MySQL и PostgreSQL сервера.
Но в этой заметке я бы хотел напомнить о еще более простом SQL сервере SQLite, который является общественным достоянием.
Этот SQL сервер конечно весьма прост - что и хорошо и плохо. Фактически он даже не использует клиент-серверную модель данных, даже никакой ConnectionString к серверу не требуется - это просто библиотечка, которая позволяет сихронно писать/читать данные (почти как в простой текстовый файлик). Но только данные можно читать/писать (почти) в полном соответствии со стандартом SQL92 - то есть командами SELECT, INSERT, UPDATE, DELETE. Можно создавать таблички командой CREATE TABLE, создавать процедуры, триггеры и так далее.
При развертывании вашей проги данные SQLite - это простой файлик в каталоге программы. И даже все стандартные драйверы доступа к SQLite устроены так, что если этого файлика нет, то он сам создается при попытки обратиться к нему. Фактически для многих-многих категорий приложений это весьма удобно - ну например если вы пишите простое настольное приложение для одного человека. Зачем вам к своему простому приложению требовать чтобы ваш потребитель развернул еще и билогетсовский SQL Server (ну хоть даже и кастрированный до состояния бесплатности)? Согласитесь удобно хранить данные и настроки проги в простом махоньком файлике (который к тому же еще и создается сам по ходу работы вашей проги).
Многие проги, такие как Skype и Firefox пользуются SQLite и хранят всякие свои полезные данные и собственные настройки в таких файликах, доступ к которым осуществляется с помощью библиотечки SQLite. На платформах, где надо экономить процессорные ресурсы и электроэнергию (Mac OS, iPhone OS, Android) SQLite является стандартным форматом хранение данных. Более подробно общие сведения об SQLite вы можете почерпнуть в инете, ну а я перейду к более конкретным вещам.
- Во-первых, конечно же SQLite можно использовать и в более сложных многопользовательских прогах, для этого надо просто брать все операции с данными в скобочки BIGIN TRANSACTION <-> END TRANSACTION. Работать в таком стиле надо осторожно, ведь у SQLite нет сложных (и дорогостоящих по вычислительным ресурсам) механизмов разграничения доступа при многопользовательской работе, транзакции в разных потоках конечно разделить можно, но если действительно требуется многопользовательский режим доступа к данным - то наверное есть смысл разворачивать MySQL. Возможно когда-нибудь позже я опубликую пример нормального многопользовательского ASP.NET сайта на SQLite - но сейчас у меня просто нет такого проекта простенького сайтика. Фактически в таком сайте нет ничего сложного - надо аккуратно брать операции доступа к данным в транзакционные скобочки или добавить еще какой-нибудь SYNLOCK на глобальную переменную SQLlite_DB. Уверен, что тысячи пользователей в день такой сайт легко потянет.
- Во-вторых, с SQLite весьма удобно работать из .NET FRAMEWORK - как из второй, так и из новой четвертой версии. На этом мы подробно остановимся ниже.
- В-третьих, SQLite - это стандартная СУБД для приложений AIR - AIR приложения для платформ Android, Macintosh и Linux и (возможно) это единственный реально удобный способ обмена данными между приложениями .NET и AIR.
Для просмотра данных в формате SQLite cуществуют десятки платных и бесплатных программ. Я бы хотел обратить внимание на пару программ - SQLite Manager (Firefox Extensions) и SQLite Administrator. Обе проги хороши, но кажется у немцев какие-то проблемы с русскими буквами (хотя воэможно это происходит только на моем кампутере).
Итак, далее я покажу как сохранить данные из приложения AIR и прочитать их из приложения .NET.
1: package
2: {
3: import flash.data.SQLConnection;
4: import flash.data.SQLResult;
5: import flash.data.SQLStatement;
6: import flash.errors.SQLError;
7: import flash.events.SQLErrorEvent;
8: import flash.events.SQLEvent;
9: import flash.filesystem.File;
10: import mx.controls.Alert;
11:
12: public class SQLite
13: {
14: public function SQLite(db_filename:String, sql_CreateTable:String)
15: {
16: DB_filename=db_filename;
17: SQL_CreateTable=sql_CreateTable;
18: }
19:
20: private var DB_filename:String;
21: private var SQL_CreateTable:String;
22: private var DBConnection:SQLConnection;
23: private var DBStatement:SQLStatement;
24:
25: public function OpenDB():String
26: {
27: var dbFile:File = File.applicationStorageDirectory.resolvePath(DB_filename);
28: DBStatement = new SQLStatement();
29 DBConnection = new SQLConnection();
30: DBStatement.sqlConnection = DBConnection;
31: DBConnection.addEventListener(SQLEvent.OPEN, onDatabaseOpen);
32: DBConnection.addEventListener(SQLErrorEvent.ERROR, onErrorHandler);
33: DBConnection.open(dbFile);
34: return dbFile.nativePath;
35: }
36:
38: private function onDatabaseOpen(event:SQLEvent):void
39: {
40: DBStatement.text = SQL_CreateTable;
41: DBStatement.addEventListener(SQLEvent.RESULT, SQLResulthandler);
42: DBStatement.addEventListener(SQLErrorEvent.ERROR, onCreateError);
43: DBStatement.execute();
44: }
45:
46: public var DB_Result:Array;
47: private function SQLResulthandler(event:SQLEvent):void
48: {
49: var result:SQLResult = DBStatement.getResult();
50: if (result != null) {
51: DB_Result = result.data;
52: }
53: }
54:
55: public function DB_Exec(SQL_Select:String):void
56: {
57: DBStatement.text = SQL_Select;
58: DBStatement.execute();
59: }
60:
61: private function onErrorHandler(error:SQLError):void
62: {
63: Alert("Error Occurred with id: " + error.errorID + " operation " + error.operation + " message " + error.message);
64: }
65: private function onCreateError(event:SQLErrorEvent):void
66: {
67: Alert("Error Occurred with id: " + event.error.errorID + " message " + event.error.message);
68: }
69: }
70: }
Соответственно вызов этого враппера выглядит вот так:
27: private var SQLite1:SQLite;
28: private var SQLite_FullFileName;
29: protected function windowedapplication1_creationCompleteHandler(event:FlexEvent):void
30: {
.....
34: SQLite1=new SQLite("avtobog.sqlite","CREATE TABLE IF NOT EXISTS Avtobog ( id INTEGER PRIMARY KEY AUTOINCREMENT, i TEXT, Date TEXT, Num TEXT, Name TEXT, Price TEXT, Group1 TEXT, Weight TEXT, Replace TEXT, Appendix1 TEXT, Appendix2 TEXT )");
35: SQLite_FullFileName=SQLite1.OpenDB();
36: }
.....
118: private function contextMenuItem_CopyToSQLite(evt:ContextMenuEvent):void {
119: CursorManager.removeAllCursors();
120: CursorManager.setBusyCursor();
121: try {
122: for(var i:int=0;i<SoapResult.length;i++)
123: {
124: SQLite1.DB_Exec("INSERT into Avtobog (i, Date, Num, Name, Price, Group1, Weight, Replace, Appendix1, Appendix2) values('" +
125: SoapResult[i].i +
126: "','" +
127: SoapResult[i].Date +
128: "','" +
129: SoapResult[i].Num +
130: "','" +
131: SoapResult[i].Name +
132: "','" +
133: SoapResult[i].Cost +
134: "','" +
135: SoapResult[i].Group +
136: "','" +
137: SoapResult[i].Weight +
138: "','" +
139: SoapResult[i].Replace +
140: "','" +
141: SoapResult[i].Appendix1 +
142: "','" +
143: SoapResult[i].Appendix2 +
144: "')");
145: }
146: Alert.show("Data save in " + SQLite_FullFileName + " (SQLite)");
147: }
148: catch (e){
149: Alert.show(e.message);
150: }
151: finally{
152: CursorManager.removeAllCursors();
153: CursorManager.removeBusyCursor();
154: }
155: }
156:
.....
Как выглядят записанные в базу этой AIR-прогой данные - вы можете увидеть на скринах выше, а теперь я покажу как взять эти данные в NET 2.0 и NET 4.0. Для начала сгружаем себе ADO.NET 2.0 Provider for SQLite.
Теперь делаем за двадцать кликов мышкой какую-нибудь простейшую тестовую формочку:
Теперь меняем фреймворк на NET 4.0 - как видите, в моей среде все работает сходу, хотя я знаю, что некоторые проггеры вручную добавляют в конфиг всякие хитрые параметры, чтобы сайт заработал под NET 4.0:
1: <configuration>
2: <startup useLegacyV2RuntimeActivationPolicy="true">
3: <supportedRuntime version="v4.0"/>
4: </startup>
5: </configuration>
Но мне этого делать не потребовалось ни в моей девелоперской среде, ни на хостинге - все пошло сразу:
Как видите, более удобное средство для обмена данными между AIR и NET невозможно придумать - буквально несколько кликов мышкой и приличные массивы данных из Flex-Flash-AIR оказываются в NET. Ну этот метод обмена локальными данными конечно не отменяет web-технологий обмена данными, о которых я писал тут - Как сделать SOAP/WSDL-вебсервис на ASP.NET/MONO для вызова его из FLEX.
|