3

J'ai installé le package SQLite-Net Extensions dans mon projet Xamarin.Android dans Visual Studio 2015 et j'essaie d'en implémenter plusieurs -to-many relation entre Person et Event entités. J'ai suivi the official documentation of the library, mais je ne peux pas le faire fonctionner.Xamarin.Android: SQLite-Net Extensions many-to-many - aucune table de ce type, collection NULL

classes I créé:

Person.cs:

[Table("People")] 
public class Person 
{ 
    [PrimaryKey, AutoIncrement] 
    public int Id { get; set; } 

    public string Name { get; set; } 

    public string LastName { get; set; } 

    public string PhoneNumber { get; set; } 

    public string Email { get; set; } 

    [ManyToMany(typeof(PersonEvent), CascadeOperations = CascadeOperation.All)] 
    public List<Event> Events { get; set; } 
} 

Event.cs:

[Table("Events")] 
public class Event 
{ 
    [PrimaryKey, AutoIncrement] 
    public int Id { get; set; } 

    public string Name { get; set; } 
    public DateTime Date { get; set; } 
    public string Place { get; set; } 

    [ManyToMany(typeof(PersonEvent), CascadeOperations = CascadeOperation.All)] 
    public List<Person> Participants { get; set; } 
} 

PersonEvent.cs:

public class PersonEvent 
{ 
    [ForeignKey(typeof(Person))] 
    public int PersonId { get; set; } 

    [ForeignKey(typeof(Event))] 
    public int EventId { get; set; } 
} 

Pour le tester, je supprimer le fichier de base de données pour être sûr un propre est créé sur le périphérique, puis essayer de créer un Person, un Event, insérez les deux dans le DB d'abord, puis attribuer le Event à le Person et d'enregistrer à nouveau en utilisant la méthode UpdateWithChildren:

var dbFile = new File(Constants.DbFilePath); 
dbFile.Delete(); 

var db = new SQLiteConnection(new SQLitePlatformAndroid(), Constants.DbFilePath); 
db.CreateTable<Person>(); 
db.CreateTable<Event>(); 
db.CreateTable<PersonEvent>(); 

var event1 = new Event 
{ 
    Name = "Volleyball", 
    Date = new DateTime(2017, 06, 18), 
    Place = "Sports hall" 
}; 

var person1 = new Person 
{ 
    Name = "A", 
    LastName = "B", 
    PhoneNumber = "123456789" 
}; 


db.Insert(person1); 
db.Insert(event1); 
person1.Events = new List<Event> { event1 }; 
db.UpdateWithChildren(person1); 

tout d'abord, je besoin d'ajouter CreateTable<PersonEvent>() ligne parce que si elle était pas présent, je recevais l'exception: SQLite.Net.SQLiteException: no such table: PersonEvent, mais je pensais que je n'ai pas créez cette table intermédiaire manuellement. SQLite-Net Extensions ne devrait-il pas le créer automatiquement?

Avec cette ligne ajoutée, les deux premières insertions de event1 et person1 fonctionnent correctement (après l'insertion des ID des deux entités). La collection Events sur person1 a même le Event créé, qui a également mis en Id: enter image description here

Cependant, la "entité opposée", dans ce cas event1 a sa collection Participants (Liste des Person) NULL:

enter image description here

J'ai tout essayé et rien ne fonctionne. Comme je l'ai compris en lisant les documents SQLite-Net Extensions, il devrait être résolu automatiquement. J'ai même ajouté ce CascadeOperations = CascadeOperation.All sur les collections, mais cela n'aide pas comme vous pouvez le voir. Je fais encore quelque chose de mal?

+0

Que se passe-t-il lorsque vous recevez une personne ou un événement de la base de données? –

+0

@ShawnKendrot Je viens d'essayer et quand je reçois les entités après le code que j'ai posté en utilisant par exemple pour Person: db.Get (1), les deux collections ('Events' dans' Person' et 'Participants' dans' Event ') sont' NULL'. – DawidSibinski

+0

@ShawnKendrot J'ai essayé et ça ne change rien. J'ai essayé de faire une seule opération en utilisant 'db.InsertWithChildren (person1)' (sans ces deux 'Insert's individuels avant), mais cela ne change rien. – DawidSibinski

Répondre

2

La collection des événements sur person1 a même l'événement créé, qui a également IDENTIF

Votre objet person1 a une liste des événements que vous avez créés. La collection contenait un lien vers l'objet event1 que vous avez créé. Cette collection d'événements n'a pas été mise à jour lorsque vous avez inséré ou mis à jour la base de données. Vous constaterez que l'objet Event a son ID défini lorsque vous l'insérez dans la base de données car la liste contient le même objet. Les extensions SQLite-NET ne sont pas une solution [auto] de chargement paresseux (comme Entity Framework). Il obtiendra des objets seulement quand on lui dit.L'utilisation de la méthode Get pour obtenir un objet de la base de données ne fait rien de différent de ce que SQLite fait déjà. C'est parce que SQLite-NET Extensions ne modifie pas cette méthode. Il offre cependant de nouvelles méthodes comme GetWithChildren et FindWithChildren. Si vous voulez obtenir les enfants d'un objet, vous avez besoin des méthodes fournies par SQLite-NET Extensions.

Les échantillons fournis utilisent ces méthodes ainsi:

// Get the object and the relationships 
var storedValuation = db.GetWithChildren<Valuation>(valuation.Id); 
if (euro.Symbol.Equals(storedValuation.Stock.Symbol)) { 
    Debug.WriteLine("Object and relationships loaded correctly!"); 
} 

Vous aussi ne voudriez pas que les objets à charger récursive de personne-événement-personne-événement-etc. comme cela ne finirait jamais. Si vous commencez avec une personne et que vous souhaitez associer toutes les personnes associées à un événement, vous souhaiterez l'obtenir dans un autre appel.

var person = db.GetWithChildren(1); 
foreach(var event in person.Events) 
{ 
    // lazy load ourselves 
    var allParticipants = db.GetWithChildren(event.Id).Participants; 
} 

espoir qui aide

+0

Merci, cela clarifie. Cependant, je me demande comment la plupart des développeurs réalisent de telles relations dans les bases de données de leur application mobile? Est-ce qu'ils utilisent un autre type de DB que SQLite? Je l'ai trouvé le plus facile à utiliser, mais peut-être y at-il de meilleures approches pour stocker les données de l'application de manière persistante? – DawidSibinski

+0

Je suppose que SQLite est le plus utilisé en ce qui concerne les bases de données. Il est disponible sur chaque plate-forme, et est très facile à utiliser –

+0

Je viens de découvrir que Entity Framework (Core) peut maintenant être utilisé avec SQLite même pour les applications Xamarin.Android - https://blog.xamarin.com/building-android -apps-with-entity-framework /. Je dois essayer. – DawidSibinski

0

Si quelqu'un veut voir plus de détails sur la création d'un grand nombre à de nombreuses relations avec la bibliothèque d'extensions SQLite-Net, contenant également des conseils et des solutions proposées ici par @Shawn Kendrot, je ve recueilli tout et wrote a post on my blog.

Espérons que ça aide :)