本記事は 2026/02/01 ~ 2026/03/01 の間毎日 AI アプリケーション開発(AI を搭載したアプリ開発 or AI を使用した開発)をテーマに 30 days AI challenge を行う 5 日目のブログポストです。
今日は RDBMS にデータを登録・データを取得する AI アプリケーションです。
親戚の家に行くと、この人誰だっけ?この人父と母のどっち方の親戚だっけ?と思うことがまれにあります。
今日はそんな関係性をデータベースに登録し管理する AI アプリケーションです。
アプリの概要
アプリの仕様としては、まずユーザーからデータのインプットを受け付けます。
ユーザーは、登録したい人物の名前や生年月日、属性や性格など関連する情報を自由記述欄に記載します。
その入力データを AI が解析し、データベースへ登録、その結果を関係図として表示する仕組みです(画像内の人物は架空の人物です)。

このように、自分とどんな関係かを表示し、祖父母であれば親からつながるような表示にしました(AI にそのように支持しました)。
※母の兄弟が母と直接つながっていないところはご愛敬

家系図であればわかりやすい樹形図のようにしようと思いましたが、今回のアプリは必ずしも家系図に使用されると限定せず、様々な人間関係に対応できるように設計しました。例えば、学校の先生や職場の上司、部下、友達など。友達が家系図の一部(自分の下や上)に入っていたら不自然ですからね。
技術観点
データベース(RDBMS)は SQL Server を使用しています。
SQL Server に対して INSERT クエリを発行しデータベースへ登録しています。
一部修正していますが、データベース登録箇所はこんな感じです。Microsoft.Data.SqlClient を使っています。ほんのちょっとだけデータベースや SQL のことを知っているので、Entity Framework の ORM ではなく .NEt Data Library を使っています(こっちのほうが好き)。
private async Task<Relation> SaveRelationAsync(string freeText, Dictionary<string, string?> parsedData)
{
var connectionString = _configuration.GetConnectionString("connectionstring");
if (string.IsNullOrEmpty(connectionString))
throw new InvalidOperationException("接続文字列 'DefaultConnection' が設定されていません");
using (var connection = new SqlConnection(connectionString))
{
await connection.OpenAsync();
// テーブル存在確認
await EnsureTableExistsAsync(connection);
var now = DateTime.UtcNow;
var dateOfBirth = TryParseDate(parsedData.GetValueOrDefault("dateOfBirth"));
using (var command = connection.CreateCommand())
{
command.CommandText = @"
INSERT INTO Table (以下省略)";
command.Parameters.AddWithValue("@param0", freeText);
command.Parameters.AddWithValue("@param1", parsedData.GetValueOrDefault("name") ?? (object)DBNull.Value);
command.Parameters.AddWithValue("@param2", parsedData.GetValueOrDefault("relationship") ?? (object)DBNull.Value);
command.Parameters.AddWithValue("@param3", dateOfBirth ?? (object)DBNull.Value);
command.Parameters.AddWithValue("@param4", parsedData.GetValueOrDefault("notes") ?? (object)DBNull.Value);
command.Parameters.AddWithValue("@CreatedAt", now);
command.Parameters.AddWithValue("@UpdatedAt", now);
var result = await command.ExecuteScalarAsync();
var id = result == null || result == DBNull.Value ? 0 : Convert.ToInt32(result);
return new Relation
{
Id = id,
FreeText = freeText,
Name = parsedData.GetValueOrDefault("param"),
Relationship = parsedData.GetValueOrDefault("param"),
DateOfBirth = dateOfBirth,
Notes = parsedData.GetValueOrDefault("param"),
CreatedAt = now,
UpdatedAt = now
};
}
}
}
データを登録する前に、ユーザーから自然言語で入力を求めているので、Gemini に入力内容を特定の形式(JSON)で返すように指定し、各項目を INSERT クエリ(ステートメント)のパラメーターとして渡すような実装としています。
※ちゃんと動くまで紆余曲折デバッグが発生したので、デバッグ用のログ出力コードを含んでいます。
private async Task<Dictionary<string, string?>> ParseRelationDataAsync(string freeText)
{
var prompt = $@"以下のユーザーの入力テキストを解析して、人間関係情報を抽出してください。
【ユーザー入力】
{freeText}
【出力形式】
JSON形式で以下の項目を返してください:
{{
""name"": ""抽出された名前(見つからない場合は null)"",
""relationship"": ""自分との関係性(親、子、兄弟、配偶者、友人など、見つからない場合は null)"",
""dateOfBirth"": ""生年月日(YYYY-MM-DD 形式、見つからない場合は null)"",
""notes"": ""その他の特徴や補足情報(見つからない場合は null)""
}}
JSONのみを返してください。説明は不要です。";
string response = string.Empty;
try
{
Console.WriteLine($"[RelationsService] Gemini API 呼び出し開始");
// タイムアウト付きでGemini APIを呼び出し(10秒待機)
var cts = new System.Threading.CancellationTokenSource(TimeSpan.FromSeconds(10));
var task = _geminiService.GetChatResponseAsync(prompt, new List<Google.GenAI.Types.Content>());
response = await task;
Console.WriteLine($"[RelationsService] Gemini API レスポンス: {response}");
}
catch (OperationCanceledException)
{
Console.WriteLine($"[RelationsService] Gemini API タイムアウト(10秒以上待機)");
// タイムアウト時は空のJSONで続行
response = "{}";
}
catch (Exception ex)
{
Console.WriteLine($"[RelationsService] Gemini API エラー: {ex.Message}");
Console.WriteLine($"[RelationsService] スタックトレース: {ex.StackTrace}");
// AI が失敗しても処理を続行
response = "{}";
}
// JSON パースを試みる
var result = new Dictionary<string, string?>
{
{ "name", null },
{ "relationship", null },
{ "dateOfBirth", null },
{ "notes", null }
};
AI に自然言語で投げ、取得する結果を任意の形式で返すように指示をすることで、加工が簡単になりますね。
おわりに
今日はやっとデータベースを絡めた実装を行えました。
今回は Local でアプリを実行しているので、Local PC にインストールした SQL Server を接続先としていますが、接続文字列を変えれば Azure SQL Database などのクラウドデータベースへ切り替えることも容易にできます。
また、自然言語から SQL クエリを発行することも簡単にできる(プロンプト次第)ので、token の上限を気にしなくてよいのであれば自然言語である程度は実装できます。ただし、単に SQL クエリを発行するより AI から結果を取得するまでのオーバーヘッドが生じるため、実装の容易さとトレードオフで AI の思考時間を容認する必要があります。
AI アプリでは自然言語を用いて簡単な実装ができますが、アプリケーションの最適化、ユーザーエクスペリエンスという観点では AI に頼らず従来のコーディングを行ったほうが良いでしょう。
本日はこの辺で、閲覧いただきありがとうございました。明日もよろしくお願いします。

コメント