2014-09-07 2 views
4

Я использую формы Xamarin, расширения SQLite.net и SQLitenet, и я не могу понять, почему то, что я ожидал бы просто, просто не работает.Таблица sqlite.net, где условие на дочерней таблице

У меня есть два класса

public class MeasurementInstanceModel 
{ 
    public MeasurementInstanceModel() 
    { 
    } 

    [PrimaryKey] 
    [AutoIncrement] 
    public int Id { 
     get; 
     set; 
    } 

    [ForeignKey(typeof(MeasurementDefinitionModel))] 
    public int MeasurementDefinitionId { 
     get; 
     set; 
    } 

    [ManyToOne(CascadeOperations = CascadeOperation.CascadeRead)] 
    public MeasurementDefinitionModel Definition { 
     get; 
     set; 
    } 

    [ForeignKey(typeof(MeasurementSubjectModel))] 
    public int MeasurementSubjectId { 
     get; 
     set; 
    } 

    [ManyToOne(CascadeOperations = CascadeOperation.CascadeRead)] 
    public MeasurementSubjectModel Subject { 
     get; 
     set; 
    } 

    public DateTime DateRecorded { 
     get; 
     set; 
    } 

    [OneToMany(CascadeOperations = CascadeOperation.All)] 
    public List<MeasurementGroupInstanceModel> MeasurementGroups { 
     get; 
     set; 
    } 
} 

и

public class MeasurementSubjectModel 
{ 


    [PrimaryKey] 
    [AutoIncrement] 
    public int Id { 
     get; 
     set; 
    } 
    public string Name { 
     get; 
     set; 
    } 

    [OneToMany (CascadeOperations = CascadeOperation.All)] 
    public List<MeasurementInstanceModel> MeasurementInstances {get;set;} 
} 

Я просто пытаюсь сделать следующий запрос, и он всегда терпит неудачу.

db.Table<MeasurementInstanceModel>().Where(w => w.Subject.Name == avariable); 

Я получаю это исключение

System.Diagnostics.Debugger.Mono_UnhandledException (ех = {System.Reflection.TargetInvocationException:. Исключение было брошено в целью вызова ---> Система .NullReferenceException: ссылка на объект не указывает на экземпляр объекта на SQLite.Net.TableQuery 1[MeasureONE.MeasurementInstanceModel].CompileExpr (System.Linq.Expressions.Expression expr, System.Collections.Generic.List 1 queryArgs) [0x00000] в: 0 в SQLite.Net.TableQuery 1[MeasureONE.MeasurementInstanceModel].CompileExpr (System.Linq.Expressions.Expression expr, System.Collections.Generic.List 1 queryArgs) [0x00000] в: 0 в SQLite .Net.TableQuery 1[MeasureONE.MeasurementInstanceModel].CompileExpr (System.Linq.Expressions.Expression expr, System.Collections.Generic.List 1 queryArgs) [0x0000 0]: 0 в SQLite.Net.TableQuery 1[MeasureONE.MeasurementInstanceModel].GenerateCommand (System.String selectionList) [0x00000] in <filename unknown>:0 at SQLite.Net.TableQuery 1 [MeasureONE.MeasurementInstanceModel] .GetEnumerator() [0x00000] в: 0 в System.Collections.Generic.List 1[MeasureONE.MeasurementInstanceModel].AddEnumerable (IEnumerable 1 перечислимой) [0x00000] в: 0 на System.Collections.Generic.List 1[MeasureONE.MeasurementInstanceModel]..ctor (IEnumerable 1 сборник) [0x00000] in: 0 at System.Linq.Enumerable.ToList [MeasurementInstanceModel] (IEnumerable 1 source) [0x00000] in <filename unknown>:0 at MeasureONE.Repository 1 [MeasureONE.MeasurementInstanceModel] .GetAll [DateTime] (System.Linq.Expressions. Выражение 1 predicate, System.Linq.Expressions.Expression 1 OrderBy, Nullable 1 descending, Nullable 1 пропуск, Nullable 1 count) [0x00094] in /Users/jean-sebastiencote/MeasureONE/MeasureONE/Models/Repository/Repository.cs:48 at MeasureONE.Repository 1 [MeasureONE.MeasurementInstanceModel] .GetAllWithChildren [DateTime] (System.Linq.Expressions.Expression 1 predicate, System.Linq.Expressions.Expression 1 OrderBy, Nullable 1 descending, Nullable 1 пропуск, Nullable 1 count) [0x00009] in /Users/jean-sebastiencote/MeasureONE/MeasureONE/Models/Repository/Repository.cs:54 at MeasureONE.MeasurementListViewModel.Load (System.Linq.Expressions.Expression 1 PRED, Нуль lable 1 skip, Nullable 1 count) [0x00049] in /Users/jean-sebastiencote/MeasureONE/MeasureONE/ViewModels/MeasurementListViewModel.cs:42 в MeasureONE.MeasurementListViewModel.Load (фильтр MeasureONE.FilterViewModel) [0x000cf] в/Пользователи/jean-sebastiencote /MeasureONE/MeasureONE/ViewModels/MeasurementListViewModel.cs:34 в MeasureONE.MeasurementListViewModel.m__1 (GalaSoft.MvvmLight.Messaging.NotificationMessage`1 msg) [0x00007] in/Пользователи/jean-sebastiencote/MeasureONE/MeasureONE/ViewModels/MeasurementListViewModel. cs: 21 at (wrapper managed-to-native) System.Reflection.MonoMethod: InternalInvoke (System.Reflection.MonoMethod, object, object [], System.Exception &) at System.Reflection.MonoMethod.Invoke (System. Объект obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object [], System.Globali zation.CultureInfo культура) [0x00000] в: 0 --- Конец внутренней трассировки стека исключений ---

Как вы можете видеть из трассировки стека, у меня есть несколько вещей в коде, например как порядок. Но все это прекрасно работает, пока у меня нет условия для детской таблицы.

ответ

7

Расширения SQLite-Net не добавляют функциональность запроса (по крайней мере, к настоящему времени). Это означает, что вы не можете получить доступ к отношениям во время запроса, потому что для этого объекта требуется JOIN, что он не выполняется. Вот почему вы получаете NullReferenceException.

Вам необходимо выполнить JOIN вручную.Заменить этот код:

db.Table<MeasurementInstanceModel>().Where(w => w.Subject.Name == avariable); 

С этим:

var result = conn.Query<MeasurementInstanceModel>(
    "SELECT * " + 
    "FROM MeasurementInstanceModel AS it " + 
    "JOIN MeasurementSubjectModel AS sb " + 
    "ON it.MeasurementSubjectId == sb.Id " + 
    "WHERE sb.Name == ?", avariable); 

Создание такого рода запросов автоматически является довольно сложным и не планируется поддерживать в ближайшем будущем в SQLite-Net Extensions.

Другой вариант использования SQLite-Net отношения Extension использует GetAllWithChildren метод для фильтрации нужных предметов, а затем перемещаться по отношениям для получения экземпляров:

var subjects = conn.GetAllWithChildren<MeasurementSubjectModel>(s => s.Name == avariable); 
var result = subjects.Select(s => s.MeasurementInstances).Distinct().ToList(); 

Таким образом, вам не придется набирать вручную ПРИСОЕДИНЯЙТЕСЬ, и результат точно такой же, однако этот вариант страдает от N+1 issue, поэтому он может понести некоторое снижение производительности.

Надеюсь, это поможет.

+0

Это то, что я сделал изначально, и это не сработало. Я не знал, что SQLite использует двойное равенство вместо единого равенства. Короче говоря, это работает. Вызывает разочарование, что этот тип дела не поддерживается. Я посмотрю, смогу ли я создать собственное решение на моей стороне, основываясь на атрибутах модели. – user1428857

+0

Я уже опасался чего-то подобного, спасибо за проверку. Тем не менее я все время спрашиваю себя, почему присоединение не поддерживается из коробки. – FloppyNotFound

Смежные вопросы