— У вас это… юзабилити плохое.
— Мне надо, чтобы было просто и удобно.
— Я не моряк, чтобы разбираться, как его крутить.
— Мне жаль вас, у вас всё так сложно и неудобно.
Взято с http://malinnikov.ru
Thinking out loud about development and etc.
Как-то раз попросил знакомый решить такую вот задачку (цитирую):
смотри есть к примеру ряд переменных
перем1
перем2
перем3
можно ли как то обратиться
к ним в цикле например
Для сч = 1 по 3 Цикл
сообщить(Перем+Сч)
КонецЦикла
<?
for($i = 0; $i<10; $i++)
{
$commonVar = "varName".$i;
$$commonVar = "new value".$i; /*в этом месте переменной с именем выражения "varName".$i присваивается значение "new value*/
echo $$commonVar."<br />";
}
?>
25 августа сего года компания DevExpress выпустила совершенно free очень полезную надстройку для Visual Studio 8 CodeRushExpress for C# and VB, скачать который можно тут.
CodeRushExpress предлагает расширенный набор функций для выделения кода, навигации в коде и объявлений классов и тд в коде.
Кроме того, CodeRush Xpress включает в себя более 50 рефакторингов, что, конечно же, просто замечательно. Если вы не счастливый обладатель полной версии CodeRush, то определенно must have в арсенале разработчика!
Замечательная тема, посвещенная Дню Программиста http://www.techdays.ru/DevDay/
Разработчики всех стран, объединяйтесь!
Итак, дошло время до практической части. Которая меня, скажем прямо, огорчила.
Так как хотелось использовать в своем проекте LinQ, а при попытке создать dbml-файлик штатными средствами студии выскакивает окошечко с ошибочкой (см. рис. ниже), то будем генерировать dbml с помощью DbMetal, о котором упоминалось в предыдущей части цикла.
Для начала создадим нашу базу данных, которая будет состоять из двух таблиц - Journal, главная таблица, в которую будут записываться факты поставки по конкретной дате, и таблица Items, в которой будут детали поставок по конктретной дате.
CREATE TABLE "journal" ("ID" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL , "Date" DATETIME DEFAULT CURRENT_DATE);
CREATE TABLE "items" ("ID" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL , "journalID" INTEGER NOT NULL , "supplier" VARCHAR DEFAULT supplier1, "store" VARCHAR DEFAULT store1, "amount" FLOAT DEFAULT 0)
@echo on
DbMetal.exe -dbml:sample.dbml -provider:Sqlite -conn="data source=sample.sqlite"
dbMetal.exe -code:sample.designer.cs -namespace:SampleDataContext -provider:Sqlite -conn="data source=sample.sqlite"
class DBClass
{
private Main _connection = null;
public DBClass()
{
_connection = new Main(new XSqlConnection("Data Source=sample.sqlite"));
}
public List GetJournal()
{
List items = new List();
items = _connection.Journal.ToList();
return items;
}
public List GetItems(int journalId)
{
List items = new List();
items = _connection.Items.Where(i => i.JournalID == journalId).ToList();
return items;
}
public Items AddItem(Items item)
{
_connection.Items.InsertOnSubmit(item);
_connection.SubmitChanges();
return item;
}
public Journal AddJournal(DateTime date)
{
Journal item = new Journal() { Date = date };
_connection.Journal.InsertOnSubmit(item);
_connection.SubmitChanges();
return item;
}
public void DeleteItem(int id)
{
_connection.Items.DeleteOnSubmit(
_connection.Items.SingleOrDefault(i => i.ID == id)
);
_connection.SubmitChanges();
}
public void DeleteJournal(int id)
{
_connection.Journal.DeleteOnSubmit(
_connection.Journal.SingleOrDefault(i => i.ID == id)
);
_connection.SubmitChanges();
}
}
private void InitTree()
{
foreach (Journal item in db.GetJournal())
{
AddJournalDate(item);
}
}
private void AddJournalDate(Journal item)
{
TreeNode node = new TreeNode(item.Date.Value.ToShortDateString());
node.Tag = item.ID;
tvJournal.Nodes[0].Nodes.Add(node);
}
private void tvJournal_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
{
if (tvJournal.SelectedNode != null && tvJournal.SelectedNode.Tag != null)
{
int journalId = 0;
if (int.TryParse(tvJournal.SelectedNode.Tag.ToString(), out journalId))
{
lvItems.Items.Clear();
foreach (Items item in db.GetItems(journalId))
{
AddItem(item);
}
}
}
}
private void AddItem(Items item)
{
ListViewItem lvi = new ListViewItem(new string[] { item.Supplier, item.Store, item.Amount.ToString() });
lvi.Tag = item.ID;
lvItems.Items.Add(lvi);
}
CREATE TRIGGER "main"."OnDelete" DELETE ON journal BEGIN Delete From items Where items.journalID = deleted.ID; END
private void button2_Click(object sender, EventArgs e)
{
int journalId = (int)tvJournal.SelectedNode.Tag;
db.DeleteJournal(journalId);
tvJournal.Nodes[0].Nodes.Remove(tvJournal.SelectedNode);
}
private void addItemToJournal_Click(object sender, EventArgs e)
{
int journalId = 0;
if (int.TryParse(tvJournal.SelectedNode.Tag.ToString(), out journalId))
{
Items item = new Items() {
Amount = float.Parse( tbAmount.Text ),
Store = tbStore.Text,
Supplier = tbSupplier.Text,
JournalID = journalId
};
AddItem(db.AddItem(item));
}
}
private void DeleteItemFromJournal_Click(object sender, EventArgs e)
{
if (lvItems.SelectedItems.Count > 0)
{
int itemID = (int)lvItems.SelectedItems[0].Tag;
db.DeleteItem(itemID);
lvItems.Items.Remove(lvItems.SelectedItems[0]);
}
}
Бывают проекты, в которых необходимо хранение данных, объем и структура которых делает хранение в обычных файлах неудобным, а использование СУБД - слишком громоздкое и дорогое решение. Представьте, для программы весом в пару мегабайт, которая спокойно умещается на флешке, ставить SQL Server. Немного утрировано, но всё же...
Для решения подобного рода проблем очень хорошо подходят embedded-БД (встраиваемые БД), например, sqlite, firebird или из области объектных бд - db4o. Конечно, им всем далеко до полноценных СУБД, но не для конкуренции с ними создавались встаиваемые БД, а для облегчения распространения приложений, использующих небольшие БД. Понятно, что для достижения этой цели пришлось чем-то жертвовать, и каждый жертвовал, чем мог :) Так как разговор в данной статье должен идти о первой из списка embedded-БД - sqlite, то давайте как раз посмотрим, чем же порадуют нас разработчики.
Как ожидается из названия, данная embedded-БД должна быть лёгкой. Это правда - размер подключаемой библиотеки со всеми фичами, как говорят разработчики, меньше 300 КБ. К тому же, с ней легко работать, ее легко внедрять в создаваемое ПО, ее легко администрировать и еще много таких "легко". Sqlite распространяется на условиях "открытого исходного кода", скачать ее можно с официального сайта http://www.sqlite.org.
Чем хороша sqlite:
Чем плоха sqlite:
Естественно, SQLite не предназначена, чтобы быть двигателем базы данных предприятия, это не вариант для использования в крупных проектах, разве как временную резервную БД (и звучит это даже как-то по-мазохистски). Как написано на официальном сайте движка, sqlite не предназначена, чтобы заменить Oracle, но для замены fopen().