Realm Platform は、洗練されたリアクティブな機能、リアルタイムのデータ同期、および堅牢なオフライン体験を備えたクロスプラットフォームのネイティブ アプリケーションのビルドに役立ちます。2 つの基礎的なコンポーネントには、クライアント サイドのライブ オブジェクト向けの組み込みデータベースである Realm Database と、リアルタイム同期やイベント ハンドリングを実現する Realm Object Server があり、Linux または Mac、Node.JS や PostgreSQL に使い慣れた人にとって、非常に有効で実用的でした。しかし、C# や Windows を好み、SQL Server で重要なデータを扱ったりする .NET 開発者にとって、Realm は十分な機能を果たしていませんでした。Realm Xamarin を使用して C# でクライアント サイドのネイティブ アプリケーションをビルドし、.NET Core のサポートを利用してサーバー サイドのアプリケーションで Realm を使用できましたが、残りの大半は標準の Microsoft スタック外で作業する必要がありました。
それも今日で終わりです。Realm Platform 全体で、重要な Microsoft スタックの技術を堅牢にサポートする Realm .NET をリリースしました。現在、配布を開始した 3 つの新機能には、.NET 用の新しいグローバル通知、および Windows/UWP における新しい同期とデータの暗号化サポートが含まれます。さらに、新しい SQL Server Connector を発表し、Realm と SQL Server 間における双方向のデータ統合を非常に簡素化し、レガシー データベースをリアルタイムかつオフライン対応のアプリケーションに切り替えるための最適な方法をモバイル開発チームに提供します。SQL Server Connector は、現在プライベートのベータ版ですが、12 月から Enterprise Edition のお客様向けに提供を開始します。
簡単な紹介として、シンプルなデモ用のビデオを用意しました。ビデオ視聴後は、グローバル通知を中心に説明した資料や、Realm .NET に関するドキュメントをご覧ください。
技術的な詳細情報
今年の夏に .NET Core のサポートを開始し、サーバー サイド アプリケーションで Realm の使用を実現しました。これにより、新しいデータをサーバーにあるユーザーの Realm に書き込み、Realm に同期処理を任せるだけで、接続したすべてのクライアントへ新しいデータを簡単に展開できるようになりました。いつでも変更可能な何千もの user-Realm があるなか、それぞれオープン インスタンスを維持するのが単に実現不可能であるように、ユーザーによる変更に対応するのは簡単なことではありませんでした。ここで活躍するのがグローバル通知です。グローバル通知は、膨大な量の Realm を監視し、変更に応じていつでも通知するように最適化されています。
本来、グローバル通知は NuGet パッケージです。で、.NET プロジェクト (.NET Core または Asp.Net、コンソール アプリ、WPF アプリのような .NET Framework プロジェクト) に追加します。そして、INotificationHandler インターフェイスを実装し、SDK 自体によって呼び出される 2 つのメソッドを公開します。ShouldHandle は、監視する Realm のパスを指定します。Notifier.StartAsync は、変更直前と直後の Realm の状態に関する詳細情報によって、監視した Realm に変更が加えられた際に呼び出されます。最後に、Notifier.StartAsync を呼び出して通知機能を起動し、登録するすべての通知ハンドラーに渡します。これの優れた点は、Realm Object Server を実行している同じインスタンスにとどまらず、このアプリをあらゆる場所にデプロイ可能であるという事です。
Azure の Text Analytics API を使用して、サポート チケットのセンチメント分析を行うハンドラーの作成時にどのように使用されるのか見てみましょう。ステップバイステップのチュートリアルをスキップしたい場合、完成したサンプルをご覧ください。
前提条件
開始する前に、次の項目が必要です。
・実行中の Text Analytics Service と API キー:Microsoft では、月 5,000 件のリクエストまで無償で提供します。
・Realm Platform Professional または Enterprise Edition のトークン:無償体験版はこちらからお申し込み下さい。
プロジェクトの設定
.NET Core アプリを作成して、次の NuGet パッケージを追加してください。
・Microsoft.ProjectOxford.Text
・Realm.Server
通知ハンドラーの設定
次のステップは、通知ハンドラーを実装します。ビルトインの RegexNotificationHandler を使用して、正規表現のマッチングで、ShouldHandle
の簡単な実装を提供します。^/.*/feedback$
の正規表現を使用して、/~/feedback
のパスからすべてのユーザー Realm を処理することができます。
[code language=”bash”]
public class FeedbackHandler : RegexNotificationHandler
{
private readonly SentimentClient _sentimentClient;
public FeedbackHandler() : base($"^/.*/feedback$")
{
_sentimentClient = new SentimentClient(“your-api-key”)
{
Url = “https://YOUR-REGION.api.cognitive.microsoft.com/text/analytics/v2.0/sentiment”
};
}
public override async Task HandleChangeAsync(IChangeDetails details)
{
// We’ll populate this in a bit
}
}
[/code]
基本的なスケルトンを作成してクライアントを追加したので、後は使い始めるだけです。内容を追加するため、クライアントが挿入して、処理を必要とするオブジェクトは次の構造であると仮定します。
[code language=”bash”]
public class Ticket : RealmObject
{
public string Description { get; set; }
public float Score { get; set; }
// Other irrelevant properties
}
[/code]
次の HandleChangeAsync
実装に向けた第 1 ステップは、そのクラスに対して何か挿入されているか確認することです。
[code language=”bash”]
if (!details.Changes.TryGetValue("Ticket", out var changeSetDetails) ||
changeSetDetails.Insertions.Length == 0)
{
// We don’t care about other objects being updated
return;
}
[/code]
そして、分析用に Azure に送信する SentimentRequest
を構築することができます。
[code language=”bash”]
var request = new SentimentRequest
{
Documents = changeSetDetails.Insertions
.Select((obj, index) => new SentimentDocument
{
Id = index.ToString(),
Text = obj.CurrentObject.Description,
Language = "en"
})
.Cast<IDocument>()
.ToList()
};
[/code]
これは、チケットの Description
値を分析するテキストとして送信し、配列内のオブジェクトの連続するインデックスを分析対象のドキュメントの Id
として割り当てています。ドキュメントの Id は、アプローチに問題がないように、リクエストの範囲内でユニークである必要があります。
次に、リクエストを送信して、レスポンスを処理します。
[code language=”bash”]
var response = await _sentimentClient.GetSentimentAsync(request);
var analyzedDocuments = response.Documents.Select(d =>
{
var ticket = changeSetDetails.Insertions[int.Parse(d.Id)];
return new
{
Score = d.Score,
TicketReference = ThreadSafeReference.Create(ticket.CurrentObject)
};
});
[/code]
興味深いのは、オブジェクト用に ThreadSafeReference
を作成していることです。同じスレッド上で変更する場合でも、ticket.CurrentObject
が属する details.CurrentRealm
は読み取り専用のため (特定のバージョンに固定されており、変更を処理中に変更が発生しないようにします)、異なる Realm のインスタンスを開いてチケットに変更を書き込みます。同じ Realm の異なるインスタンス内に同じオブジェクトを取得する場合、プライマリ キーでオブジェクトを渡すか、プライマリ キーのないオブジェクトでも機能する ThreadSafeReference
を使用することができます。
最後に、チケットに点数を書き込むことができます。
[code language=”bash”]
using (var realm = details.GetRealmForWriting())
{
foreach (var doc in analyzedDocuments)
{
var reference = realm.ResolveReference(doc.TicketReference);
realm.Write(() => reference.Score = doc.Score);
}
}
[/code]
通知ハンドラーの起動
たった今作成した通知ハンドラーを起動するには、これを NotifierConfiguration に渡す必要があります。その前に、管理ユーザーとしてログインする必要があります。
[code language=”bash”]
SyncConfiguration.SetFeatureToken(“YOUR-ROS-FEATURE-TOKEN”);
var credentials = Credentials.UsernamePassword(“username”, “password”, createUser: false);
var admin = await User.LoginAsync(credentials, new Uri("http://127.0.0.1:9080"));
[/code]
次に、構成を作成します。
[code language=”bash”]
var config = new NotifierConfiguration(admin)
{
Handlers = { new FeedbackHandler() },
};
[/code]
そして最後に、通知機能を起動します。
[code language=”bash”]
var notifier = await Notifier.StartAsync(config);
[/code]
通知を受け取る間、通知元への参照を保持してください。アプリケーションを停止する場合、ネイティブのメモリ リークを防ぐため、参照を必ず破棄してください。
実際の動作を確認する
これをテストする場合、通常の同期された Realm を開く小さなコンソール アプリを作成し、Ticket
オブジェクトを追加します。次のようになります。
[code language=”bash”]
var config = new SyncConfiguration(user, new Uri(“http://127.0.0.1:9080/~/feedback”));
using (var realm = Realm.GetInstance(config))
{
while (true)
{
var input = Console.ReadLine();
If (input == “exit”)
{
break;
}
realm.Write(() => realm.Add(new Ticket
{
Description = input
}));
}
}
[/code]
完成したサンプル
フィードバック管理用リポジトリで、ユーザーおよび従業員向けのアプリを含む完全なサンプルが含まれています。
その他製品に関する詳細は、弊社製品ページをご覧ください。
製品の詳細、価格、ライセンス体系、デモの依頼など、こちらからお気軽にお問い合わせください。
記事参照:
2017 年 11 月 14 日 Realm チーム
© Realm 2014-2017
「Announcing Realm .NET: Leveling Up Our Microsoft Support with Global Notifier & UWP Sync」