2017-11-23 1 views
0

Ich baue eine app Xamarin.Forms mit Realm als lokale Datenbank, und ich bin mit dem folgenden kämpfen.backlinking Viele-zu-1-Beziehung in Xamarin.Forms Realm mit

Die App verbraucht eine API eine JSON-Antwort wie diese geben:

[ 
    { 
     "id": "5bf7029c-1577-4739-b37a-845cee1ef70d", 
     "name": "Test", 
     "categories": [ 
      { 
       "id": "16db7cef-2f6a-4405-a004-df15864d4dde", 
       "name": "Category 1", 
       "master_id": "5bf7029c-1577-4739-b37a-845cee1ef70d", 
       "rooms": [ 
        { 
         "id": "d9246c9f-e8bb-41a9-b9a5-e21f1838de19", 
         "category_id": "16db7cef-2f6a-4405-a004-df15864d4dde", 
         "name": "Room 1", 
        }, 
        { 
         "id": "424a592d-8cb3-42a3-acbc-dc67d1ac8ddf", 
         "category_id": "16db7cef-2f6a-4405-a004-df15864d4dde", 
         "name": "Room 2", 
        } 
       ] 
      } 
     ] 
    } 
] 

Ich habe QuickType- verwendet, um C# -Klassen für mich zu generieren:

public class Master : RealmObject 
{ 
    [PrimaryKey] 
    [JsonProperty("id")] 
    public string Id { get; set; } 

    [JsonProperty("categories")] 
    public IList<Category> Categories { get; } 

    [JsonProperty("name")] 
    public string Name { get; set; } 
} 

public class Category : RealmObject 
{ 
    [PrimaryKey] 
    [JsonProperty("id")] 
    public string Id { get; set; } 

    [JsonProperty("master_id")] 
    public string MasterId { get; set; } 

    [JsonProperty("rooms")] 
    public IList<Room> Rooms { get; set; } 

    [JsonProperty("name")] 
    public string Name { get; set; } 
} 

public class Room : RealmObject 
{ 
    [PrimaryKey] 
    [JsonProperty("id")] 
    public string Id { get; set; } 

    [JsonProperty("category_id")] 
    public string CategoryId { get; set; } 

    [JsonProperty("name")] 
    public string Name { get; set; } 
} 

Mit Hilfe von Newtonsoft ich Parsen bin der eingehende JSON wird direkt an Objekte und die Datenbank mit dem folgenden Code gesendet:

IEnumerable<Master> masters = await Task.Run(() => JsonConvert.DeserializeObject<List<Master>>(json, new JsonSerializerSettings 
{ 
    MetadataPropertyHandling = MetadataPropertyHandling.Ignore, 
    DateParseHandling = DateParseHandling.None 

})); 

realm.Write(() => 
{ 
    foreach (Master master in masters) 
    { 
     realm.Add(master); 
    } 
}); 

S Bis jetzt funktioniert alles und das Master-Objekt einschließlich aller untergeordneten Objekte wird ordnungsgemäß erstellt. Ich muss jedoch problemlos auf die übergeordneten Daten zugreifen können. Zum Beispiel möchte ich in der Lage sein, den Namen der Kategorie zu erhalten, wenn ich nur ein Zimmer zur Verfügung habe, das eine Aussage wie Room.Category.Name verwendet.

Ich habe mehrere Wege versucht, dies zu erreichen, aber bisher ohne Erfolg. Ich werde auf meine Versuche eingehen, weil ich das Gefühl habe, dass ich nah beieinander bin.

Mein erster Versuch war durch das Reich Backlink-Eigenschaft verwenden und hinzugefügt, um das folgende Attribut zum Zimmer Klasse:

[Backlink(nameof(Category.Rooms))] 
public Category Category { get; } 

jedoch das Hinzufügen dieser Eigenschaft der Raumklasse führt zu diesem Fehler: Error CS0120: An object reference is required for the non-static field, method, or property 'Room.Category' (CS0120). Wenn ich mir die Beispiele auf der Realm-Website ansehe, sehe ich nur Beispiele, in denen der Backlink auf der Elternklasse statt der Kindklasse platziert ist, was ich jetzt versuche, also bin ich mir nicht sicher, ob das überhaupt möglich ist .

Mein zweiter Versuch bestand darin, die Relationen durch die JSON-Deserialisierung in umgekehrter Reihenfolge aufzufüllen, also würde die Kategorie keine Liste von Räumen enthalten, aber der Raum würde die Kategorie enthalten (und ich könnte den Backlink wie beschrieben verwenden) in den Beispielen, die ich gefunden habe). Das Ändern der C# -Modelle durch Hinzufügen der Category-Eigenschaft zu einem Raum und Ändern der Rooms-Eigenschaft in der Category-Klasse in einen Backlink führte jedoch zu leeren Beziehungen, da die Category-Eigenschaft überhaupt nicht gefüllt war. Vielleicht sollte ich die JsonSerializerSettings ändern, um diese Funktion zu aktivieren, aber ich konnte keine Informationen finden, wenn das überhaupt möglich ist.

Mein letzter Versuch war es, ein Verfahren zu schaffen, die CategoryId nutzt mir aus dem Raum-Objekt das Category-Objekt zu geben:

public Category Category 
{ 
    get 
    { 
     return Realm.Find<Category>(CategoryId); 
    } 
} 

Während dies dieser Ansatz zu arbeiten schien zunächst wird mir eine Fehlermeldung, wenn zu verwenden versuchen, Die Room.Category-Beziehung in Abfragen zu Realm (mit Linq) als Relation kann nicht von Realm verarbeitet werden. Ich habe auch eine Warnung beim Bau der App: Warning: Fody/RealmWeaver: Room.Category is not an automatic property but its type is a RealmObject which normally indicates a relationship.

Jede Hilfe zu diesem Thema wird sehr geschätzt.

Vielen Dank im Voraus.

Antwort

0

Backlink Eigenschaften sind immer Sammlungen, weil nichts von Ihnen verhindert, dass das gleiche Zimmer zu zwei verschiedenen Kategorien hinzufügen. Deshalb sind sie in den meisten Beispielen in der Klasse "Eltern" platziert.Dennoch könnte man leicht eine auf der „Kind“ Klasse hinzufügen, wenn Sie sicher sind, nur zu einem einzigen Elternteil gehört, es wird:

public class Room : RealmObject 
{ 
    // Other properties 

    // Notice that the collection may be private 
    // to avoid polluting your public API 
    [Backlink(nameof(Category.Rooms))] 
    private IQueryable<Category> Categories { get; } 

    // May also use FirstOrDefault if you can't guarantee 
    // the room will be added to a single Category 
    public Category Category => Categories.SingleOrDefault(); 
} 

Beachten Sie, dass Sie noch nicht Category nutzen können in LINQ-Ausdrücke, da es sich nicht um eine persistente Eigenschaft handelt, die Realm kennt.