4

我正在使用 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:异常已被调用的目标抛出。---> System.NullReferenceException:对象引用未设置为 SQLite.Net 上的对象实例.TableQuery 1[MeasureONE.MeasurementInstanceModel].CompileExpr (System.Linq.Expressions.Expression expr, System.Collections.Generic.List1 queryArgs) [0x00000] in :0 at SQLite.Net.TableQuery 1[MeasureONE.MeasurementInstanceModel].CompileExpr (System.Linq.Expressions.Expression expr, System.Collections.Generic.List1 queryArgs) [0x00000] in :0 at SQLite.Net.TableQuery 1[MeasureONE.MeasurementInstanceModel].CompileExpr (System.Linq.Expressions.Expression expr, System.Collections.Generic.List1 queryArgs) [0x00000] in :0 at SQLite.Net.TableQuery 1[MeasureONE.MeasurementInstanceModel].GenerateCommand (System.String selectionList) [0x00000] in <filename unknown>:0 at SQLite.Net.TableQuery1[MeasureONE .MeasurementInstanceModel].GetEnumerator () [0x00000] in :0 at System.Collections.Generic.List 1[MeasureONE.MeasurementInstanceModel].AddEnumerable (IEnumerable1 可枚举)[0x00000] in :0 at System.Collections.Generic.List 1[MeasureONE.MeasurementInstanceModel]..ctor (IEnumerable1 集合)[0x00000] in :0 在 System。 Linq.Enumerable.ToList[MeasurementInstanceModel] (IEnumerable1 source) [0x00000] in <filename unknown>:0 at MeasureONE.Repository1[MeasureONE.MeasurementInstanceModel].GetAll[DateTime] (System.Linq.Expressions.Expression 1 predicate, System.Linq.Expressions.Expression1 orderBy, Nullable 1 descending, Nullable1 skip, Nullable 1 count) [0x00094] in /Users/jean-sebastiencote/MeasureONE/MeasureONE/Models/Repository/Repository.cs:48 at MeasureONE.Repository1[MeasureONE.MeasurementInstanceModel].GetAllWithChildren[DateTime] (System.Linq.Expressions.Expression 1 predicate, System.Linq.Expressions.Expression1 orderBy, Nullable 1 descending, Nullable1 个跳过,可空1 count) [0x00009] in /Users/jean-sebastiencote/MeasureONE/MeasureONE/Models/Repository/Repository.cs:54 at MeasureONE.MeasurementListViewModel.Load (System.Linq.Expressions.Expression1 个预测,可空1 skip, Nullable1 个计数)[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 at MeasureONE.MeasurementListViewModel.m__1 (GalaSoft.MvvmLight.Messaging.NotificationMessage`1 msg) [0x00007] in /Users/jean-sebastiencote/MeasureONE/MeasureONE/ViewModels/MeasurementListViewModel.cs:21 at (包装器托管到本机) System.Reflection.MonoMethod:InternalInvoke (System.Reflection.MonoMethod,object,object[],System.Exception&) 在 System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System .Reflection.Binder 绑定器,System.Object[] 参数,System.Globalization。CultureInfoculture) [0x00000] in :0 --- 内部异常堆栈跟踪结束 ---

从堆栈跟踪中可以看出,我在代码中还有一些东西,例如 order by。但这一切都很好,只要我在子表上没有条件。

4

1 回答 1

8

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 扩展中支持。

使用 SQLite-Net 扩展关系的另一个选项是使用GetAllWithChildren方法来过滤所需的主题,然后通过关系导航以获取实例:

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

这样您就不必手动键入 JOIN 并且结果完全相同,但是此选项存在N+1 问题,因此可能会遭受一些性能损失。

希望能帮助到你。

于 2014-09-07T23:01:56.307 回答