2016-02-10 1 views
0

J'utilise Xamarin et C# pour créer une application multi-plateforme. Les extensions SQLite.Net sont utilisées pour la base de données locale. Le tableau de l'utilisateur contient une liste de registres, comme on le voit ci-dessous:Les éléments que vous avez enregistrés sont vides lors de la récupération à un moment ultérieur.

public class User 
{ 
    [PrimaryKey, AutoIncrement] 
    public int UserID { get; set; } 
    public string firstName { get; set; } 
    public string lastName { get; set; } 
    public string title { get; set; } 
    public string emailAddress { get; set; } 
    public string password { get; set; }  
    //public ObservableCollection<Register> registerList { get; set; } 

    [ManyToMany(typeof(RegStudent))] 
    public ObservableCollection<Register> Registers { get; set; } 

    public User() 
    { 
     this.Registers = new ObservableCollection<Register>(); 
    } 

    public void addRegisterAccess(Register register) 
    { 
     Registers.Add(register); 
    } 
} 

Lorsqu'un registre est fait, il est ajouté à la table de registre, puis ajouté à cette liste, fait comme ci-dessous:

//Set the register to the updated version of this register that is stored on db, 
//as current register that has been created through user input does not have an ID. 
register = database.db.GetRegisterByNameAndLocation(register.Name, register.Location); 

//Add the register to the current user list of registers. Then fetch the new info and set the current user 
// from the db. 
database.db.GetUserByEmail(currentUser.user.emailAddress).addRegisterAccess(register); 

Lorsque j'essaie d'accéder à la liste des registres, via l'objet utilisateur, il indique que la liste ne contient aucun élément.

J'ai cherché des solutions et elles semblent mentionner le SQLite UpdateWithChildren, mais cette méthode n'est pas celle qui existe dans ma connexion SQLite ou dans ma base de données. La liste des registres est une relation ManyToMany, comment la mise à jour s'intègre-t-elle à tout cela?

** EDIT: ** J'ai maintenant la méthode de mise à jour, mais semble obtenir une exception quand il est frappé. Ci-dessous la méthode dans mon « DatabaseManager » qui ajoute un registre à une liste d'utilisateurs:

public void addRegisterAccess(User user, Register register) 
    { 
     user.Registers.Add(register); 
     _connection.InsertOrReplaceWithChildren(user, true); 
    } 

L'exception ci-dessous est donnée lorsqu'un registre est ajouté, je pensais que le code pour lier les classes (avec table intermédiaire) a fait pas besoin d'être appelé par le code utilisateur?

02-10 12:09:51.662 E/AndroidRuntime(4461): Caused by: md52ce486a14f4bcd95899665e9d932190b.JavaProxyThrowable: SQLiteNetExtensions.Exceptions.IncorrectRelationshipException: User.Registers: ManyToMany relationship origin must have a foreign key defined in the intermediate type 
02-10 12:09:51.662 E/AndroidRuntime(4461): at SQLiteNetExtensions.Extensions.WriteOperations.Assert (Boolean assertion, System.Type type, System.Reflection.PropertyInfo property, System.String message) <0xd84bb6e8 + 0x00087> in <filename unknown>:0 
02-10 12:09:51.662 E/AndroidRuntime(4461): at SQLiteNetExtensions.Extensions.WriteOperations.UpdateManyToManyForeignKeys (SQLite.Net.SQLiteConnection conn, System.Object element, System.Reflection.PropertyInfo relationshipProperty) <0xd84b9750 + 0x0026b> in <filename unknown>:0 
02-10 12:09:51.662 E/AndroidRuntime(4461): at SQLiteNetExtensions.Extensions.WriteOperations.UpdateInverseForeignKeys (SQLite.Net.SQLiteConnection conn, System.Object element) <0xd84b9578 + 0x0014f> in <filename unknown>:0 
02-10 12:09:51.662 E/AndroidRuntime(4461): at SQLiteNetExtensions.Extensions.WriteOperations.UpdateWithChildren (SQLite.Net.SQLiteConnection conn, System.Object element) <0xd84b8a68 + 0x0003b> in <filename unknown>:0 
02-10 12:09:51.662 E/AndroidRuntime(4461): at SQLiteNetExtensions.Extensions.WriteOperations.InsertWithChildrenRecursive (SQLite.Net.SQLiteConnection conn, System.Object element, Boolean replace, Boolean recursive, ISet`1 objectCache) <0xd84b76f8 + 0x000af> in <filename unknown>:0 
02-10 12:09:51.662 E/AndroidRuntime(4461): at SQLiteNetExtensions.Extensions.WriteOperations.InsertOrReplaceWithChildren (SQLite.Net.SQLiteConnection conn, System.Object element, Boolean recursive) <0xd84b76a8 + 0x0002f> in <filename unknown>:0 
02-10 12:09:51.662 E/AndroidRuntime(4461): at RegistrationApp.Data.DatabaseManager.addRegisterAccess (RegistrationApp.User user, RegistrationApp.Models.Register register) <0xd84b7578 + 0x0003f> in <filename unknown>:0 
02-10 12:09:51.662 E/AndroidRuntime(4461): at RegistrationApp.CreateRegisterPage+<OnCreateButtonClicked>d__1b.MoveNext() <0xd87ad788 + 0x006c3> in <filename unknown>:0 
02-10 12:09:51.662 E/AndroidRuntime(4461): --- End of stack trace from previous location where exception was thrown --- 

Juste pour ajouter, ma classe de table intermédiaire ressemble à ceci:

public class RegUser 
    { 
     [ForeignKey(typeof(User))] 
     public int UserID { get; set; } 

     [ForeignKey(typeof(Register))] 
     public int RegisterID { get; set; } 
    } 

** EDIT: ** Ci-dessous le registre classe elle-même:

public class Register 
    { 
     [PrimaryKey, AutoIncrement] 
     public int RegisterID { get; set; } 
     public string Name { get; set; } 
     public string Type { get; set; } 
     public string Location { get; set; } 
     public DateTime Date { get; set; } 
     public string StartTime { get; set; } 
     public string EndTime { get; set; } 
     public Boolean Recurring { get; set; } 

     [ManyToMany(typeof(RegStudent), "StudentID", "Registers")] 
     public ObservableCollection<KeyValuePair<Student, string>> StudentList { get; set; } 

     [ManyToMany(typeof(RegUser), "UserID", "Registers")] 
     public ObservableCollection<User> UserList { get; set; } 

     public Register() 
     { 
      this.StudentList = new ObservableCollection<KeyValuePair<Student, string>>(); 
      this.UserList = new ObservableCollection<User>(); 
     } 

     //Adds a student to the Student List for this register, marking the string value as '-', to show the register has not been taken yet. 
     //This value will be set to the status of the student, to show them as Present, AWOL, Sick, Late, etc. 
     public void addStudent(Student student) 
     { 
      StudentList.Add(new KeyValuePair<Student, string>(student, "-")); 
     } 
    } 
+0

Essayez d'ajouter 'using SQLiteNetExtensions.Extensions;' pour rendre la méthode UpdateWithChildren disponible. – redent84

+0

@ redent84 Je ne peux pas croire que j'ai raté ça. J'ai utilisé la méthode mais elle donne une exception que je n'ai pas vue auparavant. J'ai mis à jour à la question pour montrer le code et l'exception. – user2283597

+0

@ redent84 J'essayais d'utiliser 'InsertOrUpdateWithChildren' mais j'ai essayé d'utiliser' UpdateWithChildren' à la place. Je reçois maintenant une exception différente, celle qui dit 'SQLiteNetExtensions.Exceptions.IncorrectRelationshipException: Register.StudentList: ManyToMany destination de la relation doit avoir la clé primaire' ... la seule solution que j'ai pu trouver en ligne n'a pas aidé à résoudre ce problème. Toute idée où je devrais chercher pour empêcher l'excpetion? Merci pour l'aide – user2283597

Répondre

1

Vous créez un liste de KeyValuePair et ainsi obtenir l'erreur que KeyValuePair n'a pas de clé primaire:

[ManyToMany(typeof(RegStudent), "StudentID", "Registers")] 
public ObservableCollection<KeyValuePair<Student, string>> StudentList { get; set; } 

Modifier à une liste de Student:

[ManyToMany(typeof(RegStudent), "StudentID", "Registers")] 
public ObservableCollection<Student> StudentList { get; set; } 

Si vous avez besoin de stocker des informations dans la relation, vous devez stocker dans RegUser classe:

public class RegUser 
{ 
    [ForeignKey(typeof(User))] 
    public int UserID { get; set; } 

    [ForeignKey(typeof(Register))] 
    public int RegisterID { get; set; } 

    public string Status { get; set; } 
} 

Soyez conscient que SQLite-Net Actuellement, les extensions ne prennent pas en charge les propriétés supplémentaires dans les tables intermédiaires et vous devrez récupérer ces informations manuellement:

var regUser = conn.Table<RegUser>.Where(ru => ru.UserID == user.ID && ru.RegisterID == register.ID).FirstOrDefault(); 
if (regUser != null) { 
    var status = regUser.Status; 
} 
+0

Merci pour la réponse, il corrige Cependant, le problème d'origine des listes étant vides même si des éléments ont été ajoutés, j'ai essayé d'utiliser 'UpdateWithChildren (register)' et j'ai aussi essayé 'InsertOrReplaceWithChildren (register)', au moment de la création d'un fichier. élève ou inscrit, mais les listes ne montrent toujours rien – user2283597

+0

J'ai regardé de plus près la façon dont En ajoutant des éléments à la base de données, il semble que les éléments soient correctement ajoutés, mais les listes sont toujours vides. Existe-t-il un moyen spécifique d'ajouter des éléments à une liste d'objets 'SQLiteNetExtensions'? – user2283597

+0

S'ils sont correctement ajoutés à la base de données, vous ne les récupérez peut-être pas. Pour récupérer des relations, vous devez utiliser l'une des méthodes de récupération 'WithChildren' ou utiliser la méthode' GetChildren' plus tard sur l'objet. – redent84