【问题标题】:C# Deserialize, then insert into SQLite databaseC#反序列化,然后插入SQLite数据库
【发布时间】:2017-12-23 23:29:09
【问题描述】:

我有以下用于模型项目的 JSON,我无法更改:

[
    {
        "id": 3,
        "description": "Project A"
    },
    {
        "id": 6,
        "description": "Project B",
        "updated_at": "2017-07-13T09:30:51+02:00",
        "created_at": "2017-07-13T09:30:51+02:00"
    }
]

我有以下用于模型任务的 JSON,我无法更改:

[
    {
        "id": 3,
        "project": {
            "id": 3,
            "description": "Project A"
        },
        "description": "Task 1"
    },
    {
        "id": 6,
        "project": {
            "id": 3,
            "description": "Project A"
        },
        "description": "Task 2"
    },
    {
        "id": 9,
        "project": {
            "id": 3,
            "description": "Project A"
        },
        "description": "Task 3"
    },
    {
        "id": 12,
        "project": {
            "id": 6,
            "description": "Project B"
        },
        "description": "Task 4"
    }
]

我有以下两种型号:

using SQLite.Net.Attributes;
using SQLiteNetExtensions.Attributes;

namespace BettyMultiModel.Resources.Model
{
    public class Models
    {

    }

    class Project : Models
    {

        public int Id { get; set; }
        public string Description { get; set; }

    }

    class Task : Models
    {

        public int Id { get; set; }
        public string Description { get; set; }   

    }
}

我使用这种方法将 JSON 导入 SQLite 数据库:

// Insert Records of type TType into database.
private async Task<string> InsertRecords<TType>(HttpResponseMessage response)
        where TType : Models
{
    try
    {
        DataBase db = new DataBase();

        string responseString = await response.Content.ReadAsStringAsync();
        var responseBody = JsonConvert.DeserializeObject<List<TType>>(responseString);


        foreach (TType item in responseBody)
        {
            bool resultInsert = db.Insert(item);
        }

        return ResponseToMessage(response, "Insert Records");
    }
    catch (Exception ex)
    {
        Log.Info("DeserializeObject", ex.Message);
        throw;
    }            

}

当我只想拥有两个模型的 Id 和 Description 属性时,这很好用。但我也想将 Project 模型与 Task 模型/项目 ID 之间的关系存储在 Task 模型中。

当我使用http://json2csharp.com/ 的任务解析 JSON 时,我得到以下模型建议:

public class Project
{
    public int id { get; set; }
    public string description { get; set; }
}

public class RootObject // Which is Task
{
    public int id { get; set; }
    public Project project { get; set; }  // <-------- Extra property
    public string description { get; set; }
}

使用这样的模型 - 将 RootObject 重命名为 Task - 会导致异常:NotSupportedException: Don't know about BettyMultiModel.Resources.Model.Project

所以我把类改成:

using SQLite.Net.Attributes;
using SQLiteNetExtensions.Attributes;

namespace BettyMultiModel.Resources.Model
{
    public class Models
    {

    }

    class Project : Models
    {

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

    }

    class Task : Models
    {

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

        [OneToMany]
        public Project project { get; set; }

    }
}

不再抛出异常,但是当我查看 db 文件时,仍然只有 Id 和 Description 列,并且没有引用两个模型之间的关系。

我在这里错过了什么?

编辑:添加了创建表格的方法

public void ClearTable<TType>()
        where TType : Models
{
    try
    {
        Log.Info("Folder DB: ", dbPath);

        using (var connection = new SQLiteConnection(platform, dbPath))
        {
            connection.DropTable<TType>();
            connection.CreateTable<TType>();
        }
    }
    catch (SQLiteException ex)
    {
        Log.Info("SQLiteEx", ex.Message);
    }

}

编辑:快到了……

我也犯了一个小错误,一个项目有很多任务,所以属性应该是[ManyToOne]。 db 中的表现在看起来不错。项目 ID 只是没有插入到 Task 模型内的 ProjectId 列中。每行都有值 0。我想我需要弄清楚如何将嵌套项目对象的 id 映射到 Task 类的 ProjectId 属性。

我尝试过像这样使用 Newtonsoft.Json 命名空间,它在 Task 模型中插入 1 行,然后由于记录 id 的唯一性而开始抛出错误。 JsonProperty("id") 将其标识为任务的 ID,而不是项目的 ID:

[JsonProperty("id"), ForeignKey(typeof(Project))]
public int ProjectId { get; set; }

这些是现在的模型:

class Project : Models
{

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

    public string Description { get; set; }

}

class Task : Models
{

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

    public string Description { get; set; }

    [ForeignKey(typeof(Project))]
    public int ProjectId { get; set; }

    [ManyToOne]
    public Project Project { get; set; }

}

【问题讨论】:

  • 数据库结构是如何生成的?我想你在某处调用“CreateTable(type)”?如果你这样做,也许你错过了一个 CreateTable(typeof(Project));
  • @TomTom:确实。我已经在底部添加了方法。

标签: c# json sqlite


【解决方案1】:

假设,在您的问题中,您使用的是 Twin Coders SQLite-Net-Extensions 包,我认为您定义模型的方式有误。

如果您查看链接 Bitbucket 页面中的 多对一 部分,您需要在 ManyToOne 属性之外定义一个 ForeignKey 属性。这是他们的例子(注意 Person 类的 Bus 和 BusId 属性):

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

    public string PlateNumber { get; set; }
}

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

    public string Name { get; set; }

    [ForeignKey(typeof(Bus))]
    public int BusId { get; set; }

    [ManyToOne]
    public Bus Bus { get; set; }
}

对于您的代码,我相信您所要做的就是使用以下模型:

class Project : Models
{
    [PrimaryKey]
    public int Id { get; set; }

    public string Description { get; set; }

    // The id of the task used in the relationship (this gets stored in the DB)
    [ForeignKey(typeof(Task))]
    public int TaskId { get; set; }

    // Meaning you have many projects to one task
    [ManyToOne]
    public Task Task { get; set; }
}

class Task : Models
{
    [PrimaryKey]
    public int Id { get; set; }

    public string Description { get; set; }
}

【讨论】:

  • 这非常接近解决方案。我在 ManyToOne 上犯了一个小错误,这必须是 OneToMany。我希望在我的帖子底部看到上一期的更新。谢谢!
  • 没问题。当然属性应该是 JsonProperty("projectId")?
  • 另外,您更新的模型 [ManyToOne] 表示您对每个项目都有许多任务。这是想要的吗?如果您希望每个任务有多个项目,我会将外键移到 Project 中,就像答案中一样。
  • 不幸的是它不像 JsonProperty("projectId") 或 JsonProperty("ProjectId") 那样简单。它将如何引用 JSON 对象“项目”? '[ManyToOne]' 属性是正确的。一个项目可以有一个或多个任务对象。网上有很多例子如何反序列化对象内的数组,但我找不到任何对象内的对象/嵌套对象。
  • 没问题,如果你回到这个问题,我可以推荐 Entity Framework Core。我个人更喜欢它,并且与 SQLite 和 SqlServer 兼容。 docs.microsoft.com/en-us/ef/core
猜你喜欢
  • 2020-02-19
  • 1970-01-01
  • 2010-10-18
  • 2016-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-17
相关资源
最近更新 更多