😎

[C#/VB.NET]LiteDBをVB.NETでも使いたくてC#でDLL化した

2023/06/17に公開

LiteDB を VB.NET でも使いたい

LiteDB とは C#で書かれた NoSQL で SQLite よりも簡単に使えるのでちょっとしたアプリ等には個人的には使いやすいなと思っているデータベースです。
また、DLL も SQLite より軽量ですし exe をひとまとめにもできます。
SQLite は DLL から DLL を呼ぶような形になっており、1 個の exe ファイルにまとめて配布したいなんて時に個人的には使いにくかったです。(もしうまく 1 個の exe にまとめられる方法知っている方がいれば是非教えてください)

そんな使いやすい LiteDB ですが、VB.NET では NuGet からインストールしても使えなかったように思います。
そこで多少制限は付きますが、裏技的な方法をご紹介します。
C#でクラスライブラリを作って DLL にして VB.NET から参照する方法です。

下記、C#で LiteDB をクラス化して使いやすくしたコードの例です。
クラス化してクラス外からアクセスする都合上、値の取り出しは全部一気に取り出すか ID を指定して取り出す方法しか書いてません。
名前は適当に MyClassLibrary としています。
また、LiteDB の NuGet 空のインストール方法とクラスライブラリで DLL を作成する方法については割愛します。

using LiteDB;
using System;
using System.Collections.Generic;
using System.Linq;

namespace MyClassLibrary
{
    /// <summary>
    /// LiteDB用のクラスにはidが必須なので
    /// インターフェースでidを持ったクラスの実装を制約
    /// </summary>
    public interface IId
    {
        int id { get; }
    }

    /// <summary>
    /// LiteDB用のクラス
    /// </summary>
    public class LiteDB
    {
        /// <summary>
        /// データベースのパス
        /// </summary>
        private readonly string _dbFilePath;

        /// <summary>
        /// データベースのテーブル名
        /// </summary>
        private readonly string _dbTable;

        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="dbFilePath"></param>
        /// <param name="dbTabale"></param>
        public LiteDB(string dbFilePath, string dbTabale)
        {
            _dbFilePath = dbFilePath;
            _dbTable = dbTabale;
        }

        /// <summary>
        /// 1レコード追加
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entry"></param>
        /// <returns></returns>
        public bool Insert<T>(T entry)
        {
            try
            {
                using (var db = new LiteDatabase(_dbFilePath))
                {
                    var col = db.GetCollection<T>(_dbTable);
                    col.Insert(entry);
                }
            }
            catch (Exception)
            {
                return false;
            }
            return true;
        }

        /// <summary>
        /// 複数レコードをリストで追加
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entries"></param>
        /// <returns></returns>
        public bool InsertList<T>(IEnumerable<T> entries)
        {
            try
            {
                using (var db = new LiteDatabase(_dbFilePath))
                {
                    var col = db.GetCollection<T>(_dbTable);
                    col.Insert(entries);
                }
            }
            catch (Exception)
            {
                return false;
            }
            return true;
        }

        /// <summary>
        /// 全件取得
        /// </summary>
        /// <param name="tableNmae"></param>
        /// <returns></returns>
        public List<T> GetAllData<T>()
        {
            using (var db = new LiteDatabase(_dbFilePath))
            {
                var col = db.GetCollection<T>(_dbTable);
                var query = col.Query().ToEnumerable().ToList();
                return query;
            }
        }

        /// <summary>
        /// 1レコード取得
        /// </summary>
        /// <param name="tableName"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        public T GetOneRecord<T>(int id) where T : IId
        {
            using (var db = new LiteDatabase(_dbFilePath))
            {
                var col = db.GetCollection<T>(_dbTable);
                T record = col.FindOne(x => x.id == id);
                return record;
            }
        }

        /// <summary>
        /// 1レコード更新
        /// </summary>
        /// <param name="tableName"></param>
        /// <param name="id"></param>
        /// <param name="updateObj"></param>
        public void Update<T>(T updateObj) where T : IId
        {
            using (var db = new LiteDatabase(_dbFilePath))
            {
                var col = db.GetCollection<T>(_dbTable);
                T record = col.FindOne(x => x.id == updateObj.id);

                record = updateObj;

                col.Update(record);
            }
        }

        /// <summary>
        /// 1レコード削除
        /// </summary>
        /// <param name="tableName"></param>
        /// <param name="id"></param>
        public void Delete<T>(int id)
        {
            using (var db = new LiteDatabase(_dbFilePath))
            {
                var col = db.GetCollection<T>(_dbTable);
                col.Delete(id);
            }
        }

        /// <summary>
        /// 全レコード削除
        /// </summary>
        /// <param name="tableName"></param>
        /// <param name="id"></param>
        public void DeleteAll<T>()
        {
            using (var db = new LiteDatabase(_dbFilePath))
            {
                var col = db.GetCollection<T>(_dbTable);
                col.DeleteAll();
            }
        }
    }
}

このクラスで DLL を作成して、参照に追加したら VB.NET からはこのように呼び出せます。

'自作ライブラリを呼び出す
Imports MyClassLibrary

'IIDを継承したクラスを作成
Friend Class SampleData
        Implements IId
        'Id番号は自動採番される
        Public Property id As Integer Implements IId.id
        Public Property Title As String
        Public Property Name As String
End Class

'データベースのパスとテーブル名
Dim filePath = "./sample.db"
Dim tableName = "sample"

'適当なデータを作成
Dim sampleData = New List(Of SampleData) From {
        New SampleData With {
                .Title = "Title",
                .Name = "Name"
        },
        New SampleData With {
                .Title = "Title",
                .Name = "Taro"
        },
        New SampleData With {
                .Title = "Test",
                .Name = "Test"
        }
        }

'LiteDBのインスタンス作成
Dim liteDB = New MyClassLibrary.LiteDB(filePath, tableName)

'データのInsert(単体)
liteDB.Insert(New SampleData With {
        .Title = "First",
        .Name = "Test"
})

'データのInsert(複数)
liteDB.InsertList(sampleData)

'全レコードの取得
Dim result = liteDB.GetAllData(Of SampleData)()

'1レコードの取得(ID指定のみ)
Dim record = liteDB.GetOneRecord(Of SampleData)(4)

'レコードの更新
liteDB.Update(Of SampleData)(New SampleData With {
            .id = 1,
            .Title = "Change",
            .Name = "Name"
        })

'1レコードの削除(ID指定のみ)
liteDB.Delete(Of SampleData)(4)

'レコードの全件削除
liteDB.DeleteAll(Of SampleData)()

これで ID でしか検索出来ないという制約はあるものの VB.NET からでも LiteDB を使えるようになりました。
細かい条件での検索は全件取得して LINQ で検索で代用しましょう。

ちなみに C#でこのクラス(ライブラリ)を使う場合は下記の様になります。

//自作ライブラリを呼び出す
using MyClassLibrary;

//IIDを継承したクラスを作成
 internal class SampleData : IId
    {
        //Id番号は自動採番される
        public int id { get; set; }
        public string Title { get; set; }
        public string Name { get; set; }
    }

//データベースのパスとテーブル名
var filePath = @"./sample.db";
var tableName = "sample";

//適当なデータを作成
var sampleData = new List<SampleData> {
new SampleData
{
        Title = "Title",
        Name = "Name",
},
new SampleData
{
        Title="Title",
        Name="Taro",
},
new SampleData
{
        Title="Test",
        Name="Test",
}
};

//LiteDBのインスタンス作成
var liteDB = new MyClassLibrary.LiteDB(filePath, tableName);

//データのInsert(複数)
liteDB.InsertList(sampleData);

//全レコードの取得
var result = liteDB.GetAllData<SampleData>();

//1レコードの取得(ID指定のみ)
var record = liteDB.GetOneRecord<SampleData>(4);

//レコードの更新
liteDB.Update<SampleData>( new SampleData
        {
        id = 1,
        Title = "Change",
        Name = "Name"
        });

//1レコードの削除(ID指定のみ)
liteDB.Delete<SampleData>(4);


//レコードの全件削除
liteDB.DeleteAll<SampleData>();

以上。
このコードで何か不具合があっても責任はとれませんのでご承知おきください。

Discussion