前提
これ以上説明すると分かりやすすぎるRealmをXamarinで動かす方法の記事を読んでいること(読んでいると話がスムーズです。)
Owner
クラスとDog
クラスが有ること。(↑の記事にあります。)Xamarin Studio(Community版でもOK)が入ってること。
やること
Dog
モデルから以下のことを行います。
- 取り出し
- id指定取り出し
- 挿入
- id指定更新
- 全削除
- id指定削除
免責事項
私がこれでやりやすいと思っていただけで、これがRealmらしい書き方かは保証できません。
もし、これより正しいやり方をご存知でしたら編集リクエストやコメントでお願いします。
Dogを修正
以前のよりも主キーのSSN
が増えてます。
Owner
クラスは使ってないため、Dogから消してもいいかもしれません。
Swift版を知ってる方
Swift版と違い、SwiftではprimaryKey()
のオーバーライドだけで主キー設定ができましたが、[ObjectId]
のAttributeがついています。
using System;
using System.Collections.Generic;
using Realms;
namespace 自分のプロジェクト名
{
// Define your models like regular C# classes
public class Dog : RealmObject
{
[ObjectId]
public string SSN { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public Person Owner { get; set; }
}
public class Person : RealmObject
{
public string Name { get; set; }
public RealmList<Dog> Dogs { get; }
}
}
コントローラを作成
Dog
モデルから操作するクラスをScripts/Controllers/DogController.cs
に作成した。
今回、Scripts
フォルダを作成し、その中にControllers
フォルダを作成しています。
using Realms;
using System.Diagnostics;
using System.Linq;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace 自分のプロジェクト名
{
public class DogController
{
private Realm realm;
public DogController ()
{
this.realm = Realm.GetInstance();
}
public void Insert(Dog newDog)
{
// トランザクションを用いてオブジェクトを保存・更新します.
this.realm.Write(() =>
{
var id = this.Count();
var mydog = realm.CreateObject<Dog>();
mydog.SSN = (id).ToString ();
mydog.Name = newDog.Name;
mydog.Age = newDog.Age;
});
}
public void Update(string id, Dog dog)
{
if (this.CountById(id) == 0)
{
return;
}
var res = this.realm.All<Dog>().Where(d => d.SSN == id).Single();
using(var trans = realm.BeginWrite())
{
res.Name = dog.Name;
res.Age = dog.Age;
res.Owner = dog.Owner;
trans.Commit();
}
}
public Dog FindById(string id)
{
if (this.CountById(id) == 0)
{
return null;
}
return this.realm.All<Dog>().Where(d => d.SSN == id).Single();
}
public Dog[] FindAll()
{
return this.realm.All<Dog>().ToArray();
}
public int Count()
{
return this.realm.All<Dog>().Count();
}
public int CountById(string id)
{
return this.realm.All<Dog>().Where(d => d.SSN == id).Count();
}
public void DeleteAll()
{
// トランザクションを開始してオブジェクトを削除します.
using (var trans = this.realm.BeginWrite())
{
// これはだめ.
// foreach (var dog in realm.All<Dog>())
// {
// this.realm.Remove(dog);
// }
this.realm.RemoveAll<Dog>();
trans.Commit();
}
}
public void DeleteById(string id)
{
var obj = this.FindById(id);
if (obj == null)
{
return;
}
// Delete an object with a transaction
using (var trans = this.realm.BeginWrite ()) {
this.realm.Remove(obj);
trans.Commit();
}
}
}
}
主キーは自分でインクリメントすることになります。面倒ですが・・。自動でいいのに。
実行するには
まず古いRealm消す。
以前実行した場合、Realmのデータが残っています。
手順はAndroidのエミュレータです。
アプリごと消します。
※もっといい消し方があればコメントお願いします。
Realmファイルを消す手順です
注意!・・・この手順は面倒なので、もしもっと楽な方法があると思うので教えて下さい。
このクラスは自由です。
SetDB()
メソッドを実行しましょう。
Dump()
メソッドは中身を出力するために記載しました。
private void SetDB()
{
Debug.WriteLine(new string('*', 10));
var dc = new DogController ();
dc.DeleteAll();
var myDog = new Dog() { Name = "一郎", Age = 10 };
var myDog2 = new Dog() { Name = "次郎", Age = 11 };
var myDog3 = new Dog() { Name = "三郎", Age = 12 };
dc.Insert(myDog);
dc.Insert(myDog2);
dc.Insert(myDog3);
Debug.WriteLine(new string('*', 10));
Debug.WriteLine("count:{0}", dc.Count());
var dogs = dc.FindAll();
this.Dump(dogs);
dc.DeleteById("1");
dc.DeleteById("1");
dogs = dc.FindAll();
this.Dump(dogs);
var newDog = new Dog() { Name = "ネオドッグ", Age = 22 };
dc.Update("5", newDog);
dogs = dc.FindAll();
this.Dump(dogs);
}
private void Dump(Dog[] dogs)
{
// ダンプする.
foreach (var dog in dogs)
{
Debug.WriteLine("id:{0}, name:{1}, age:{2}",
dog.SSN, dog.Name, dog.Age);
Debug.WriteLine(new string('-', 10));
}
}
}
実行した時の効果。
- 一郎、次郎、三郎の犬を3匹追加。
- カウントも出してます。
- 主キー
id
はDogConrtroller
のおかげで自動でインクリメントされます。 - id
1
を指定して、2回消しています。これはあえて実験のため。エラーにならないように対処してます。 - id
5
に対して更新しています。しかし5
はいないので何も起こりません。id2
の次郎や3
の三郎に対して行えば、ネオドッグに変化するはずです。
次回
今回Dog限定でその都度クラスが必要なので、Genericsクラスで汎用的にできるものを作成予定です。