🤖 はじめに
「AIチャットから直接DBを操作できたら、業務はもっと楽になるはず…」
.NET 9 と Function Calling の登場で、C#開発者なら一度はそう考えたことがあるかもしれません。ユーザーが「A製品の在庫を教えて」と話しかけるだけで、GetStock()メソッドが走り、AIが流暢な日本語で回答する。そんな未来はもうすぐそこです。
しかし、データの読み取り(Read)は第一歩です。一歩進んだ活用として、データの作成(Create)、更新(Update)、削除(Delete)、すなわちCRUD操作をAIに任せるという可能性があります。
この強力な機能には、慎重な設計が求められます。この記事では、AIチャットによるCRUD操作のリスクを管理し、C#とFunction Callingで安全に実装するための4つの設計原則を、具体的なコードと共に提案します。
結論:AIによるCRUDは「可能」だが、それは新たな設計課題の始まり
いきなり結論から言います。AIチャットからのCRUD操作は、技術的には可能です。しかし、その実現には、従来のシステム設計とは異なるアプローチが求められます。
AIの役割は、あくまで優秀なアシスタント。AIの能力を最大限に引き出しつつ、システムの安全性を確保するためには、AIを「直接の実行者」から「実行前の最終確認を準備するアシスタント」へと役割を明確に定義する設計思想が鍵となります。

🛡️ 安全なAI-CRUDを実現する4つの設計原則
安全な実装のためには、以下の4つの設計原則をコードレベルで徹底することが極めて重要です。
原則1:【最重要】人間による最終確認ステップ
自然言語には、どうしても曖昧さがつきまといます。「田中さんのアカウントを消して」という指示が、どの「田中さん」を指すのか、AIが100%正確に判断できる保証はありません。
ユーザー: 「営業部の田中太郎さんのアカウントを無効にしてください」
AIの応答: (
DisableUserAccount関数を呼び出す準備をしつつ)「営業部に所属する『田中 太郎』さんのアカウントを無効化します。この操作は元に戻せません。よろしいですか?」
[はい、実行します] [キャンセル]
ユーザーが明確な意思で「はい」ボタンをクリックして初めて、C#側で実際の更新処理を実行します。
このステップを設けることで、AIの誤解釈によって意図しないデータが変更・削除されるリスクを大幅に低減できます。
原則2:厳格な権限管理
チャットの向こう側にいるユーザーが誰で、そのユーザーに本当にマスタ更新の権限があるのかをチェックするロジックは、AI任せにせず、必ずアプリケーション側(C#)で実装します。
AIに権限を尋ねさせるような実装は、セキュリティ上の脆弱性となるため避けるべきです。権限チェックは、常にサーバーサイドの責務です。
原則3:操作内容の明確化
AIが操作対象を一つに特定できなかった場合、勝手に推測させてはいけません。必ずユーザーに選択を促し、意図を明確化させるべきです。
ユーザー: 「田中さんのアカウントを削除して」
AIの応答:
「システムには2名の『田中』さんが登録されています。どちらのアカウントを削除しますか?」
田中 太郎(営業部)田中 花子(経理部)
このように、候補を提示してユーザーに選ばせることで、操作の正確性を担保します。
原則4:すべての操作のログ記録と監査
「誰が」「いつ」「どのような自然言語の指示で」「どのデータを変更したのか」をすべてログに記録する仕組みは必須です。
通常の操作ログに加えて、トリガーとなったチャットの原文も一緒に保存しておくことで、万が一問題が発生した際の原因追跡や監査が格段に容易になります。
💻 C#での実装イメージ
補足:「Function CallingでAIに関数を教える」とは?
具体的なコードを見る前に、前提知識を整理しましょう。
「Function CallingでAIに関数を教える」とは、コードの**「説明文」をAIに渡すこと**を意味します。具体的には、C#のメソッドに付けたXMLコメント(<summary>や<param>)を、Azure OpenAI SDKのようなライブラリがAIの理解できる形式(JSON)に変換し、ユーザーの質問と一緒にAPIへ送信します。
AIは、ユーザーの文章と、渡された関数の説明リスト(「この関数は〇〇ができます」というカタログのようなもの)を読んで、どの関数をどの引数で呼び出すべきかを判断し、その結果をC#アプリケーションに返します。
つまり、これから見るコードのように**「C#のメソッドに分かりやすい説明書(XMLコメント)を書いておくこと」**が、AIに関数を教える、というステップに相当します。
コード例
上記の4つの設計原則を念頭に置いたC#のメソッド実装例を見てみましょう。
// Function CallingでAIにこの関数の存在を教える
// XMLコメントで、AIに関数の目的やパラメータの意味を詳しく説明するのがコツです。
/// <summary>
/// 指定された製品IDの価格を更新します。実行には管理者権限が必要です。
/// </summary>
/// <param name="productId">価格を更新する製品のID</param>
/// <param name="newPrice">新しい価格</param>
public async Task<string> UpdateProductPrice(int productId, decimal newPrice)
{
// === 原則2: 権限管理 ===
// 実際のアプリケーションでは、HTTPコンテキストなどから認証済みユーザーを取得します。
var currentUser = await GetAuthenticatedUserAsync();
if (!currentUser.IsInRole("Administrator"))
{
// AIは、このエラーメッセージを元にユーザーに応答します。
return "エラー: 価格を更新する権限がありません。";
}
// === 原則3: 曖昧さの排除(データ存在確認) ===
var product = await _dbContext.Products.FindAsync(productId);
if (product == null)
{
return $"エラー: 製品ID '{productId}' が見つかりません。";
}
// === 原則1: 最終確認(このメソッドが呼ばれる前のステップ) ===
// このメソッド自体は、ユーザーがUI上で「はい、実行します」と
// クリックした後に呼び出されることを想定しています。
// そのため、ここでは直接DBを更新します。
// === 原則4: ログ記録 ===
LogOperation(currentUser.Id, $"UpdateProductPrice(productId: {productId}, newPrice: {newPrice})");
// 3. 実際のDB更新処理
product.Price = newPrice;
await _dbContext.SaveChangesAsync();
// 4. 成功した旨を返す
// この文字列を元に、AIが最終的な応答を生成します。
return $"製品 '{product.Name}' の価格を {newPrice:C} に更新しました。";
}
✨ まとめ
チャットインターフェースを通じたCRUD操作は、業務システムの利便性を飛躍的に向上させる大きな可能性を秘めています。
しかし、その実装には、データの読み取りとは次元の違う慎重さが求められます。
- 原則1:必ず、人間による最終確認ステップを設ける
- 原則2:権限チェックは、AIではなくC#側で厳格に行う
- 原則3:曖昧な指示は、ユーザーに問い直して明確化させる
- 原則4:すべての操作を監査可能な形でログに残す
これらの原則を守り、「セキュリティ・ファースト」の精神で設計することで、AIの力を安全に、最大限に引き出すことができます。C#開発者の皆さん、この新しいフロンティアを、ぜひ責任ある形で開拓していきましょう。




