SQLite-Net 扩展 - GetAllWithChildrenAsync 没有拉动一切

Posted

技术标签:

【中文标题】SQLite-Net 扩展 - GetAllWithChildrenAsync 没有拉动一切【英文标题】:SQLite-Net Extensions - GetAllWithChildrenAsync not pulling everything 【发布时间】:2021-04-26 14:14:45 【问题描述】:

我正在尝试使用 SQLite-Net 扩展来创建关系数据库。尝试从数据库中提取 Term 对象时遇到问题。它成功地提取了相关的课程,但没有提取与课程相关的评估和笔记。我不确定问题是否在于我如何将对象插入数据库,如何从数据库中提取对象,或者我如何列出对象属性。

我觉得 SQLite-Net Extensions 文档非常有限,所以我什至不确定发生了什么。我尝试了很多不同的方法,包括添加 CascadeOperations,但这些方法似乎都没有帮助。

这是我的对象的(简化的)代码:

[Table("Terms")]
public class Term

    [PrimaryKey, AutoIncrement]
    public int ID  get; set; 
    public string Name  get; set; 
    [OneToMany]
    public List<Course> Courses  get; set; 

    public Term()  
    public Term(string name, List<Course> courses)
    
        Name = name;
        Courses = courses;
    

课程

[Table("Courses")]
public class Course

    [PrimaryKey, AutoIncrement]
    public int ID  get; set; 
    [ForeignKey(typeof(Term))]
    public int TermID  get; set; 
    public string Name  get; set; 
    [OneToMany]
    public List<Assessment> Assessments  get; set; 
    [OneToMany]
    public List<Note> Notes  get; set; 

    public Course()  

    public Course(string name, List<Assessment> assessments, List<Note> notes)
    
        Name = name;
        Assessments = assessments;
        Notes = notes;
    

评估

[Table("Assessments")]
public class Assessment

    [PrimaryKey, AutoIncrement]
    public int ID  get; set; 
    [ForeignKey(typeof(Course))]
    public int CourseID  get; set; 
    public string Name  get; set; 

    public Assessment()  
    public Assessment(string name)
    
        Name = name;
    

注意事项

[Table("Notes")]
public class Note

    [PrimaryKey, AutoIncrement]
    public int ID  get; set; 
    [ForeignKey(typeof(Course))]
    public int CourseID  get; set; 
    public string Name  get; set; 
    public string Text  get; set; 

    public Note()  
    public Note(string name, string note)
    
        Name = name;
        Text = note;
    

下面是插入和获取对象的代码: 插入

public bool SaveTermAsync(Term term)
    
        if (term.ID != 0)
        
            _database.UpdateWithChildrenAsync(term);
            return true;
        
        else
        
            foreach (var course in term.Courses)
            
                foreach (var assessment in course.Assessments)
                
                    _database.InsertAsync(assessment);
                
                foreach (var note in course.Notes)
                
                    _database.InsertAsync(note);
                
                _database.InsertAsync(course);
            
            _database.InsertAsync(term);
            _database.UpdateWithChildrenAsync(term);
            return false;
        
    

得到

public Task<List<Term>> GetTermsAsync()
    
        return _database.GetAllWithChildrenAsync<Term>();
    

我知道这有点像代码转储,但我不知道哪里或哪里出了问题。如果有人可以提供任何有关可能出现问题的信息,那就太好了。也许我只是在期待会发生一些实际上并非如此的事情。我不知道。

另外,如果有人有任何比https://bitbucket.org/twincoders/sqlite-net-extensions/src/master/ 更好的文档的链接,那就太棒了

编辑

我也尝试使用 Cascading Options、CascadeRead、CascadeInsert 和 CascadeAll。将 CascadeInsert 或 CascadeAll 与 _database.InsertWithChildrenAsync(term, true) 一起使用会导致崩溃。崩溃没有提供任何错误消息,甚至用 try catch 块包装 InsertWithChildren 也不起作用。删除递归 bool 导致程序不会崩溃,并且实际上最接近我正在寻找的内容。评估和注释不再为空,但仍为空。这是我更新的代码:

保存和获取:

public async Task<List<Term>> GetTermsAsync()
    
        return await _database.GetAllWithChildrenAsync<Term>(recursive: true);
    

public async void SaveTermAsync(Term term)
    
        if (term.ID != 0)
        
            await _database.UpdateWithChildrenAsync(term);
        
        else
        
            //Trying this with recursion results in crash
            await _database.InsertWithChildrenAsync(term);
        
    

一对多关系:

//In Term
[OneToMany(CascadeOperations = CascadeOperation.All)]
public List<Course> Courses  get; set; 

//In Courses
[OneToMany(CascadeOperations = CascadeOperation.All)]
public List<Assessment> Assessments  get; set; 
[OneToMany(CascadeOperations = CascadeOperation.All)]
public List<Note> Notes  get; set; 

另外,我忘了包括上次我是如何填充表格的。

public bool CreateTables()
    
        _database.CreateTableAsync<Term>().Wait();
        _database.CreateTableAsync<Course>().Wait();
        _database.CreateTableAsync<Assessment>().Wait();
        _database.CreateTableAsync<Note>().Wait();
        return true;
    

    public Task<int> ClearTablesTest()
    
        _database.DropTableAsync<Term>();
        _database.DropTableAsync<Course>();
        _database.DropTableAsync<Assessment>();
        return _database.DropTableAsync<Note>();
    

async public Task<int> PopulateTestData()
    
        await ClearTablesTest();
        CreateTables();

        Term term = new Term("Test Term", true, DateTime.Now, DateTime.Now.AddDays(10),
            new List<Course>
            
                new Course("Test Course", CourseStatus.Completed, "Guys Name", "(999)-999-9999", "email@gmail.com", 6, DateTime.Now, DateTime.Now.AddDays(10),
                new List<Assessment>
                
                    new Assessment("Test Assessment", AssessmentType.Objective, false, DateTime.Now, DateTime.Now.AddDays(10))
                ,
                new List<Note>
                
                    new Note("Test Note", "This is a test note.")
                )
            );
        App.Database.SaveTermAsync(term);
        return 0;
    

【问题讨论】:

我觉得如果你只是使用Insert的话,你需要在keys创建好之后手动建立关系。为避免这种情况,请使用 InsertWithChildren。您是否真的检查了 db 表以确定是否正确创建了关系? 我尝试过使用 InsertWithChildren,但它似乎并没有改变任何东西。当我调用 GetAllWithChildrenAsync 来获取学期时,会返回课程列表,但无论我是否执行 InsertWithChildren,评估和注释都是空的。至于检查数据库表,我不确定你的意思。有没有办法检查关系是否存在? 您可以使用多种 SQLite 管理工具来检查您的数据库。查看表格并验证 FK 和 PK id 在数据中的设置是否符合您的预期。 @Jason 你有这些 SQLite 管理工具的例子吗? google.com/search?q=sqlite+management+tools 【参考方案1】:

我终于弄清楚了导致崩溃的原因以及在 SQLite-Net 扩展中造成一般混乱的原因。

在我的评估类中,属性

public string BackgroundColor
    
        get  return IsComplete ? "#558f45" : "Gray"; 
        set  BackgroundColor = value; 
    

在使用递归时导致崩溃。我已经在网上搜索了两个多星期来寻找这个问题的解决方案,但没有找到类似的东西。我提交了一份关于 SQLite-Net Extensions bitbucket 的错误报告。

如果有人知道为什么这条特定的线路会导致问题,我很想听听您的意见。在此之前,我会将此问题标记为已回答并继续在我的应用程序上工作。

感谢 @redent84 迄今为止在此问题上提供的帮助。

【讨论】:

那段代码不是递归调用setter吗? 是的,这是在我对 SQLite-Net Extensions 的错误报告中向我指出的。我不敢相信我错过了这么简单的事情。

以上是关于SQLite-Net 扩展 - GetAllWithChildrenAsync 没有拉动一切的主要内容,如果未能解决你的问题,请参考以下文章

C#使用sqlite-net搭建简易的ORM

调试符号时读取 SQLite-net.dll 失败

Xamarin 项目中 SQLite-Net 的通用存储库

使用带有 sqlite-net orm 的 SQLiteConnection.Delete(object) 命令后更改 sqlite 文件大小

如何在带有 ARM CPU 的 WinRT 设备中部署 SQLite?

system.reflection.targetinvocationexception SQLite