Skip to content

Instantly share code, notes, and snippets.

@ishisaka
Created March 6, 2014 08:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ishisaka/9384937 to your computer and use it in GitHub Desktop.
Save ishisaka/9384937 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Microsoft.Isam.Esent.Interop;
namespace EsentSample
{
internal class Program
{
private static void Main(string[] args)
{
Database db = new Database();
db.CreateInstance();
db.CreateDatabase();
var ev1 = new Event {Id = Guid.NewGuid(), Description = "Test", Price = 100.0, StartTime = DateTime.Now};
db.AddEvent(ev1);
var events = db.GetAllEvents();
foreach (var ev in events)
{
Console.WriteLine(ev.ToString());
}
Console.ReadLine();
}
}
public class Event
{
public Guid Id { get; set; }
public string Description { get; set; }
public double Price { get; set; }
public DateTime StartTime { get; set; }
public override string ToString()
{
return String.Format("{0}, {1}, {2:F2}, {3}", Id, Description, Price, StartTime);
}
}
public class Database
{
private Instance _instance;
private string _instancePath;
private string _databasePath;
private const string DabaseName = "Database";
public void CreateInstance()
{
_instancePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, DabaseName);
_databasePath = Path.Combine(_instancePath, "database.edb");
_instance = new Instance(_databasePath);
//Configure Instance
_instance.Parameters.CreatePathIfNotExist = true;
_instance.Parameters.TempDirectory = Path.Combine(_instancePath, "temp");
_instance.Parameters.SystemDirectory = Path.Combine(_instancePath, "system");
_instance.Parameters.LogFileDirectory = Path.Combine(_instancePath, "logs");
_instance.Parameters.Recovery = true;
_instance.Parameters.CircularLog = true;
_instance.Init();
}
public void CreateDatabase()
{
using (var session = new Session(_instance))
{
// create database file
JET_DBID database;
Api.JetCreateDatabase(session, _databasePath, null, out database, CreateDatabaseGrbit.OverwriteExisting);
// create database schema
using (var transaction = new Transaction(session))
{
JET_TABLEID tableid;
Api.JetCreateTable(session, database, "Events", 1, 100, out tableid);
// ID
JET_COLUMNID columnid;
Api.JetAddColumn(session, tableid, "Id",
new JET_COLUMNDEF
{
cbMax = 16,
coltyp = JET_coltyp.Binary,
grbit = ColumndefGrbit.ColumnFixed | ColumndefGrbit.ColumnNotNULL
}, null, 0, out columnid);
// Description
Api.JetAddColumn(session, tableid, "Description",
new JET_COLUMNDEF
{
coltyp = JET_coltyp.LongText,
cp = JET_CP.Unicode,
grbit = ColumndefGrbit.None
}, null, 0, out columnid);
// Price
Api.JetAddColumn(session, tableid, "Price",
new JET_COLUMNDEF
{
coltyp = JET_coltyp.IEEEDouble,
grbit = ColumndefGrbit.None
}, null, 0, out columnid);
// StartTime
Api.JetAddColumn(session, tableid, "StartTime",
new JET_COLUMNDEF
{
coltyp = JET_coltyp.Currency,
grbit = ColumndefGrbit.None
}, null, 0, out columnid);
// Define table indices
var indexDef = "+Id\0\0";
Api.JetCreateIndex(session, tableid, "id_index",
CreateIndexGrbit.IndexPrimary, indexDef, indexDef.Length, 100);
indexDef = "+Price\0\0";
Api.JetCreateIndex(session, tableid, "price_index",
CreateIndexGrbit.IndexDisallowNull, indexDef, indexDef.Length, 100);
transaction.Commit(CommitTransactionGrbit.None);
}
Api.JetCloseDatabase(session, database, CloseDatabaseGrbit.None);
Api.JetDetachDatabase(session, _databasePath);
}
}
/// <summary>
/// データベース操作
/// </summary>
/// <param name="dataFunc">トランザクション</param>
/// <returns>作業結果</returns>
private IList<Event> ExecuteInTransaction(Func<Session, Table, IList<Event>> dataFunc)
{
IList<Event> results;
using (var session = new Session(_instance))
{
JET_DBID dbid;
Api.JetAttachDatabase(session, _databasePath, AttachDatabaseGrbit.None);
Api.JetOpenDatabase(session, _databasePath, String.Empty, out dbid, OpenDatabaseGrbit.None);
using (var transaction = new Transaction(session))
{
using (var table = new Table(session, dbid, "Events", OpenTableGrbit.None))
{
results = dataFunc(session, table);
}
transaction.Commit(CommitTransactionGrbit.None);
}
}
return results;
}
/// <summary>
/// Eventをテーブルに追加する
/// </summary>
/// <param name="ev">Eventオブジェクト</param>
public void AddEvent(Event ev)
{
ExecuteInTransaction((session, table) =>
{
using (var updater = new Update(session, table, JET_prep.Insert))
{
var columnId = Api.GetTableColumnid(session, table, "Id");
Api.SetColumn(session, table, columnId, ev.Id);
var columnDesc = Api.GetTableColumnid(session, table, "Description");
Api.SetColumn(session, table, columnDesc, ev.Description, Encoding.Unicode);
var columnPrice = Api.GetTableColumnid(session, table, "Price");
Api.SetColumn(session, table, columnPrice, ev.Price);
var columnStartTime = Api.GetTableColumnid(session, table, "StartTime");
Api.SetColumn(session, table, columnStartTime, DateTime.Now.Ticks);
updater.Save();
}
return null;
});
}
/// <summary>
/// 指定されたIdのデータをテーブルから削除する
/// </summary>
/// <param name="id">Id</param>
public void Delete(Guid id)
{
ExecuteInTransaction((session, table) =>
{
Api.JetSetCurrentIndex(session, table, null);
Api.MakeKey(session, table, id, MakeKeyGrbit.NewKey);
if (Api.TrySeek(session, table, SeekGrbit.SeekEQ))
{
Api.JetDelete(session, table);
}
return null;
});
}
/// <summary>
/// 全てのデータを取得する
/// </summary>
/// <returns>Eventのリスト</returns>
public IList<Event> GetAllEvents()
{
return ExecuteInTransaction((session, table) =>
{
var results = new List<Event>();
if (Api.TryMoveFirst(session, table))
{
do
{
results.Add(GetEvent(session, table));
} while (Api.TryMoveNext(session, table));
}
return results;
});
}
/// <summary>
/// Eventを取得する
/// </summary>
/// <param name="session">Sessionオブジェクト</param>
/// <param name="table">Tableオブジェクト</param>
/// <returns>Eventオブジェクト</returns>
private Event GetEvent(Session session, Table table)
{
var ev = new Event();
var columnId = Api.GetTableColumnid(session, table, "Id");
ev.Id = Api.RetrieveColumnAsGuid(session, table, columnId) ?? Guid.Empty;
var columnDesc = Api.GetTableColumnid(session, table, "Description");
ev.Description = Api.RetrieveColumnAsString(session, table, columnDesc, Encoding.Unicode);
var columnPrice = Api.GetTableColumnid(session, table, "Price");
ev.Price = Api.RetrieveColumnAsDouble(session, table, columnPrice) ?? 0;
var columnStartTime = Api.GetTableColumnid(session, table, "StartTime");
var ticks = Api.RetrieveColumnAsInt64(session, table, columnStartTime);
if (ticks.HasValue)
{
ev.StartTime = new DateTime(ticks.Value);
}
return ev;
}
/// <summary>
/// Idを指定してEventを取得する
/// </summary>
/// <param name="id">Id</param>
/// <returns>Eventオブジェクト</returns>
public IList<Event> GetEventsById(Guid id)
{
return ExecuteInTransaction((session, table) =>
{
var results = new List<Event>();
Api.JetSetCurrentIndex(session, table, null);
Api.MakeKey(session, table, id, MakeKeyGrbit.NewKey);
if (Api.TrySeek(session, table, SeekGrbit.SeekEQ))
{
results.Add(GetEvent(session, table));
}
return results;
});
}
/// <summary>
/// Priceの範囲でデータを取得する
/// </summary>
/// <param name="minPrice">最小値</param>
/// <param name="maxPrice">最大値</param>
/// <returns>Eventオブジェクトのリスト</returns>
public IList<Event> GetEventsForPriceRange(double minPrice, double maxPrice)
{
return ExecuteInTransaction((session, table) =>
{
var results = new List<Event>();
Api.JetSetCurrentIndex(session, table, "price_index");
Api.MakeKey(session, table, minPrice, MakeKeyGrbit.NewKey);
if (Api.TrySeek(session, table, SeekGrbit.SeekGE))
{
Api.MakeKey(session, table, maxPrice, MakeKeyGrbit.NewKey);
Api.JetSetIndexRange(session, table,
SetIndexRangeGrbit.RangeUpperLimit | SetIndexRangeGrbit.RangeInclusive);
do
{
results.Add(GetEvent(session, table));
} while (Api.TryMoveNext(session, table));
}
return results;
});
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment