我使用的是Xamarin表单,SQLite.net和SQLitenet扩展,我无法弄清楚为什么我希望简单的东西不起作用。
我有两个班级
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(ex = {System.Reflection.TargetInvocationException:调用目标已抛出异常.---&gt; System.NullReferenceException:未将对象引用设置为对象的实例 在SQLite.Net.TableQuery
1[MeasureONE.MeasurementInstanceModel].CompileExpr (System.Linq.Expressions.Expression expr, System.Collections.Generic.List
1 queryArgs)[0x00000] in:0 在SQLite.Net.TableQuery1[MeasureONE.MeasurementInstanceModel].CompileExpr (System.Linq.Expressions.Expression expr, System.Collections.Generic.List
1 queryArgs)[0x00000] in:0 在SQLite.Net.TableQuery1[MeasureONE.MeasurementInstanceModel].CompileExpr (System.Linq.Expressions.Expression expr, System.Collections.Generic.List
1 queryArgs)[0x00000] in:0 在SQLite.Net.TableQuery1[MeasureONE.MeasurementInstanceModel].GenerateCommand (System.String selectionList) [0x00000] in <filename unknown>:0 at SQLite.Net.TableQuery
1 [MeasureONE.MeasurementInstanceModel] .GetEnumerator()[0x00000] in:0 at System.Collections.Generic.List1[MeasureONE.MeasurementInstanceModel].AddEnumerable (IEnumerable
1 enumerable)[0x00000] in:0 在System.Collections.Generic.List1[MeasureONE.MeasurementInstanceModel]..ctor (IEnumerable
1集合)[0x00000] in:0 at System.Linq.Enumerable.ToList [MeasurementInstanceModel](IEnumerable1 source) [0x00000] in <filename unknown>:0 at MeasureONE.Repository
1 [MeasureONE.MeasurementInstanceModel] .GetAll [DateTime](System.Linq.Expressions.Expression1 predicate, System.Linq.Expressions.Expression
1 orderBy,Nullable {{1} } 1 skip,Nullable1 descending, Nullable
1 [MeasureONE.MeasurementInstanceModel] .GetAllWithChildren [DateTime](System.Linq.Expressions.Expression1 count) [0x00094] in /Users/jean-sebastiencote/MeasureONE/MeasureONE/Models/Repository/Repository.cs:48 at MeasureONE.Repository
1 orderBy,Nullable1 predicate, System.Linq.Expressions.Expression
1 skip,Nullable {{1 1个pred,Nullable1 descending, Nullable
1个计数)[0x00049] /Users/jean-sebastiencote/MeasureONE/MeasureONE/ViewModels/MeasurementListViewModel.cs:42 在MeasureONE.MeasurementListViewModel.Load(MeasureONE.FilterViewModel过滤器)[0x000cf] /Users/jean-sebastiencote/MeasureONE/MeasureONE/ViewModels/MeasurementListViewModel.cs:34 在MeasureONE.MeasurementListViewModel.m__1(GalaSoft.MvvmLight.Messaging.NotificationMessage`1 msg)[0x00007] in /Users/jean-sebastiencote/MeasureONE/MeasureONE/ViewModels/MeasurementListViewModel.cs:21 at(wrapper managed-to-native)System.Reflection.MonoMethod:InternalInvoke(System.Reflection.MonoMethod,object,object [],System.Exception&amp;) 在System.Reflection.MonoMethod.Invoke(System.Object obj,BindingFlags invokeAttr,System.Reflection.Binder binder,System.Object [] parameters,System.Globalization.CultureInfo culture)[0x00000] in:0 ---内部异常堆栈跟踪结束---
从堆栈跟踪中可以看出,代码中还有一些内容,例如order by。但这一切都很好,只要我没有儿童餐桌上的条件。
答案 0 :(得分:7)
SQLite-Net Extensions没有添加任何查询功能(至少到现在为止)。这意味着您无法在查询时访问关系,因为该对象需要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();
这样您就不必手动键入JOIN,结果完全相同,但是此选项会受N+1 issue的影响,因此可能会受到一些性能损失。
希望它有所帮助。