using System.Data;
using System.Data.SQLite;
using Dapper;
namespace OCES.Resonance.Core;
public static class Database
{
static readonly string DefaultConnectionString = "Data Source=default.db;Version=3;";
///
/// 获取数据库连接
///
/// 数据库名称(不含扩展名)
/// 数据库连接
public static IDbConnection GetConnection(string dbName = "default")
{
string connectionString = $"Data Source={dbName}.db;Version=3;";
return new SQLiteConnection(connectionString);
}
///
/// 初始化数据库表结构
///
public static void InitializeDatabase()
{
using var connection = GetConnection();
connection.Open();
const string sql = @"
CREATE TABLE IF NOT EXISTS sounds (
id INTEGER PRIMARY KEY AUTOINCREMENT,
unique_id TEXT NOT NULL UNIQUE,
short_id TEXT,
md5 TEXT NOT NULL,
path TEXT NOT NULL,
filename TEXT NOT NULL,
folder TEXT NOT NULL,
directory TEXT NOT NULL,
duration REAL NOT NULL,
total_samples INTEGER NOT NULL,
bit_depth INTEGER NOT NULL,
channels INTEGER NOT NULL,
sample_rate INTEGER NOT NULL,
type TEXT NOT NULL,
date_added TEXT NOT NULL,
original_modification_date TEXT NOT NULL,
origination_time TEXT NOT NULL,
bpm REAL,
frame_rate TEXT,
timecode INTEGER,
description TEXT,
category TEXT,
subcategory TEXT,
cat_id TEXT,
category_full TEXT,
genre TEXT,
style TEXT,
mood TEXT,
keywords TEXT,
rating INTEGER,
artist TEXT,
composer TEXT,
designer TEXT,
recordist TEXT,
publisher TEXT,
manufacturer TEXT,
originator TEXT,
originator_ref TEXT,
project_name TEXT,
library TEXT,
cd_title TEXT,
track_title TEXT,
episode TEXT,
scene TEXT,
take TEXT,
tape TEXT,
cue_number INTEGER,
sync_point INTEGER,
release_date TEXT,
track_year TEXT,
is_edited INTEGER,
is_split INTEGER,
location TEXT,
[group] TEXT,
markers TEXT,
comments TEXT,
notes TEXT,
copyright TEXT,
coding_history TEXT,
microphone TEXT,
mic_perspective TEXT,
user1 TEXT,
user2 TEXT,
user3 TEXT,
user4 TEXT,
user5 TEXT,
user6 TEXT,
user7 TEXT,
user8 TEXT,
INDEX idx_md5 (md5),
INDEX idx_path (path),
INDEX idx_unique_id (unique_id)
);
";
connection.Execute(sql);
}
///
/// 添加单条音频记录
///
/// 音频元数据
/// 是否添加成功
public static bool AddEntry(AudioFileMeta meta)
{
try
{
using var connection = GetConnection();
connection.Open();
const string sql = @"
INSERT INTO audio_files (
unique_id, short_id, md5, path, filename, folder, directory,
duration, total_samples, bit_depth, channels, sample_rate, type,
date_added, original_modification_date, origination_time,
bpm, frame_rate, timecode, description, category, subcategory,
cat_id, category_full, genre, style, mood, keywords, rating,
artist, composer, designer, recordist, publisher, manufacturer,
originator, originator_ref, project_name, library, cd_title,
track_title, episode, scene, take, tape, cue_number, sync_point,
release_date, track_year, is_edited, is_split, location, [group],
markers, comments, notes, copyright, coding_history, microphone,
mic_perspective, user1, user2, user3, user4, user5, user6, user7, user8
) VALUES (
@UniqueId, @ShortId, @Md5, @Path, @Filename, @Folder, @Directory,
@Duration, @TotalSamples, @BitDepth, @Channels, @SampleRate, @Type,
@DateAdded, @OriginalModificationDate, @OriginationTime,
@Bpm, @FrameRate, @Timecode, @Description, @Category, @Subcategory,
@CatId, @CategoryFull, @Genre, @Style, @Mood, @Keywords, @Rating,
@Artist, @Composer, @Designer, @Recordist, @Publisher, @Manufacturer,
@BwfOriginator, @BwfOriginatorRef, @ProjectName, @Library, @CdTitle,
@TrackTitle, @Episode, @Scene, @Take, @Tape, @CueNumber, @SyncPoint,
@ReleaseDate, @TrackYear, @IsEdited, @IsSplit, @Location, @Group,
@Markers, @Comments, @Notes, @Copyright, @CodingHistory, @Microphone,
@MicPerspective, @User1, @User2, @User3, @User4, @User5, @User6, @User7, @User8
);
";
connection.Execute(sql, meta);
return true;
}
catch (Exception)
{
return false;
}
}
///
/// 批量添加音频记录
///
/// 音频元数据列表
/// 成功添加的记录数
public static int AddEntries(IEnumerable entries)
{
var count = 0;
using var connection = GetConnection();
connection.Open();
using var transaction = connection.BeginTransaction();
try
{
const string sql = @"
INSERT INTO audio_files (
unique_id, short_id, md5, path, filename, folder, directory,
duration, total_samples, bit_depth, channels, sample_rate, type,
date_added, original_modification_date, origination_time,
bpm, frame_rate, timecode, description, category, subcategory,
cat_id, category_full, genre, style, mood, keywords, rating,
artist, composer, designer, recordist, publisher, manufacturer,
originator, originator_ref, project_name, library, cd_title,
track_title, episode, scene, take, tape, cue_number, sync_point,
release_date, track_year, is_edited, is_split, location, [group],
markers, comments, notes, copyright, coding_history, microphone,
mic_perspective, user1, user2, user3, user4, user5, user6, user7, user8
) VALUES (
@UniqueId, @ShortId, @Md5, @Path, @Filename, @Folder, @Directory,
@Duration, @TotalSamples, @BitDepth, @Channels, @SampleRate, @Type,
@DateAdded, @OriginalModificationDate, @OriginationTime,
@Bpm, @FrameRate, @Timecode, @Description, @Category, @Subcategory,
@CatId, @CategoryFull, @Genre, @Style, @Mood, @Keywords, @Rating,
@Artist, @Composer, @Designer, @Recordist, @Publisher, @Manufacturer,
@BwfOriginator, @BwfOriginatorRef, @ProjectName, @Library, @CdTitle,
@TrackTitle, @Episode, @Scene, @Take, @Tape, @CueNumber, @SyncPoint,
@ReleaseDate, @TrackYear, @IsEdited, @IsSplit, @Location, @Group,
@Markers, @Comments, @Notes, @Copyright, @CodingHistory, @Microphone,
@MicPerspective, @User1, @User2, @User3, @User4, @User5, @User6, @User7, @User8
);
";
foreach (var entry in entries)
{
connection.Execute(sql, entry, transaction);
count++;
}
transaction.Commit();
}
catch (Exception)
{
transaction.Rollback();
throw;
}
return count;
}
///
/// 检查记录是否已存在
///
/// 文件 MD5 值
/// 文件路径
/// 是否存在
public static bool EntryExists(string md5, string filePath)
{
using var connection = GetConnection();
connection.Open();
const string sql = @"
SELECT COUNT(*) FROM audio_files
WHERE md5 = @Md5 OR path = @Path;
";
var count = connection.ExecuteScalar(sql, new { Md5 = md5, Path = filePath });
return count > 0;
}
}