在 Entity Framework 中使用 SQLite 创建外键:

huangapple go评论86阅读模式
英文:

Creating a foreign key in Entity Framework using SQLite

问题

CheckList

public class CheckList
{
    [PrimaryKey, AutoIncrement]
    public int CheckListID { get; set; }

    [Required]
    [SQLite.MaxLength(50)]
    public string name { get; set; }

    // 这一行是你遇到问题的地方
    // 你可以尝试使用以下代码来解决问题
    // public int? CheckListItemID { get; set; }
    // [ForeignKey(nameof(CheckListItemID))]
    public ICollection<CheckListItem> CheckListItems { get; set; }
}

CheckListItem

public class CheckListItem
{
    [PrimaryKey, AutoIncrement]
    public int CheckListItemID { get; set; }

    public string ItemText { get; set; }
    public bool isChecked { get; set; }
    public int ItemOrder { get; set; }

    // foreign key
    [ForeignKey("CheckList")]
    public int CheckListID { get; set; }
    public CheckList CheckList { get; set; }
}

MainPage.xml 保持不变。

英文:

I'm using Entity Framework Core 7 in a .NET Maui app with SQLite to store relational data using two data models.

CheckList:

using SQLite;
using SQLiteTest.DataModels;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace SQLiteTest.DataModels
{
    public class CheckList
    {
        [PrimaryKey, AutoIncrement]
        public int CheckListID { get; set; }

        [Required]
        [SQLite.MaxLength(50)]
        public string name { get; set; }

        public ICollection&lt;CheckListItem&gt; CheckListItems { get; set; }
    }
}

CheckListItem:

using SQLite;
using SQLiteTest.DataModels;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace SQLiteTest.DataModels
{
    public class CheckListItem
    {
        [PrimaryKey, AutoIncrement]
        public int CheckListItemID { get; set; }

        public string ItemText { get; set; }
        public bool isChecked { get; set; }
        public int ItemOrder { get; set; }

        // foreign key
        [ForeignKey(&quot;CheckList&quot;)]
        public int CheckListID { get; set; }
        public CheckList CheckList { get; set; }
    }
}

MainPage.xml:

using SQLite;
using SQLiteTest.DataModels;

namespace SQLiteTest;

public partial class MainPage : ContentPage
{
    private SQLiteConnection _database;

    public MainPage()
    {
	    InitializeComponent();

        var dbPath = Path.Combine(@&quot;D:\TESTDATA&quot;, &quot;dbtest.db&quot;);
        _database = new SQLiteConnection(dbPath);

        _database.CreateTable&lt;CheckList&gt;();
        _database.CreateTable&lt;CheckListItem&gt;();
    }
}

I get an exception on:

_database.CreateTable&lt;CheckList&gt;();

> Exception: System.NotSupportedException: 'Don't know about system.Collections.Generic.ICollection`1 [SQLiteTest.DataModels.CheckListItem]'

If I remove:

public ICollection&lt;CheckListItem&gt; CheckListItems { get; set; }

Then it creates the table, but not the foreign key. I believe the error has to do with CheckList not knowing what a type CheckListItem is. If I create CheckListItem first:

_database.CreateTable&lt;CheckListItem&gt;();

I get the exception on that line:

> System.NotSupportedException: 'Don't know about SQLiteTest.DataModels.CheckList'

However, it does resolve in code and compiles without warning or error. Is this error thrown because table CheckListItems doesn't exist in database yet?

Updated after running migrations (looks like the foreign key relationships is built?)

public partial class InitialCreate : Migration
{
    /// &lt;inheritdoc /&gt;
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.CreateTable(
            name: &quot;List&quot;,
            columns: table =&gt; new
            {
                listID = table.Column&lt;long&gt;(type: &quot;INTEGER&quot;, nullable: false),
                name = table.Column&lt;string&gt;(type: &quot;TEXT&quot;, nullable: false),
                CheckList = table.Column&lt;long&gt;(type: &quot;INTEGER&quot;, nullable: false)
            },
            constraints: table =&gt;
            {
                table.PrimaryKey(&quot;PK_List&quot;, x =&gt; x.ListID);
            });

        migrationBuilder.CreateTable(
            name: &quot;CheckListItem&quot;,
            columns: table =&gt; new
            {
                CheckListItemID = table.Column&lt;long&gt;(type: &quot;INTEGER&quot;, nullable: false),
                question = table.Column&lt;string&gt;(type: &quot;TEXT&quot;, nullable: false),
                order = table.Column&lt;long&gt;(type: &quot;INTEGER&quot;, nullable: false),
                isChecked = table.Column&lt;long&gt;(type: &quot;INTEGER&quot;, nullable: true)
            },
            constraints: table =&gt;
            {
                table.PrimaryKey(&quot;PK_CheckListItem&quot;, x =&gt; x.CheckListItemID);
            });

        migrationBuilder.CreateTable(
            name: &quot;CheckList&quot;,
            columns: table =&gt; new
            {
                CheckListID = table.Column&lt;long&gt;(type: &quot;INTEGER&quot;, nullable: false),
                name = table.Column&lt;string&gt;(type: &quot;TEXT&quot;, nullable: false),
                CheckListItem = table.Column&lt;long&gt;(type: &quot;INTEGER&quot;, nullable: false)
            },
            constraints: table =&gt;
            {
                table.PrimaryKey(&quot;PK_CheckList&quot;, x =&gt; x.CheckListID);
                table.ForeignKey(
                    name: &quot;FK_CheckList_CheckListItem_CheckListItem&quot;,
                    column: x =&gt; x.CheckListItem,
                    principalTable: &quot;CheckListItem&quot;,
                    principalColumn: &quot;CheckListItemID&quot;);
            });

        migrationBuilder.CreateIndex(
            name: &quot;IX_CheckList_CheckListItem&quot;,
            table: &quot;CheckList&quot;,
            column: &quot;CheckListItem&quot;);
    }

    /// &lt;inheritdoc /&gt;
    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropTable(
            name: &quot;List&quot;);

        migrationBuilder.DropTable(
            name: &quot;CheckList&quot;);

        migrationBuilder.DropTable(
            name: &quot;CheckListItem&quot;);
    }
}

答案1

得分: 1

SQLite 不支持这种方式的外键,因此会出现 NotSupportedException。查看文档 你需要依赖于 ChecklistsItems 中的 Checklist 的键。

public class CheckList
{
    [PrimaryKey, AutoIncrement]
    public int CheckListID { get; set; }

    [Required]
    [SQLite.MaxLength(50)]
    public string name { get; set; }
}

public class CheckListItem
{
    [PrimaryKey, AutoIncrement]
    public int CheckListItemID { get; set; }

    public string ItemText { get; set; }
    public bool isChecked { get; set; }
    public int ItemOrder { get; set; }

    public int CheckListID { get; set; }
}

另外,值得注意的是,使用 EF 可能会让你的生活更加复杂。最好遵循 Microsoft 的建议,使用 sqlite-net-pcl,根据 Maui 文档 进行操作。

英文:

SQLite do not support foreign key in that fashion, hence the NotSupportedException.
See documentation What you need to do is rely on the Key to the Checklist in the ChecklistsItems.

public class CheckList
{
    [PrimaryKey, AutoIncrement]
    public int CheckListID { get; set; }

    [Required]
    [SQLite.MaxLength(50)]
    public string name { get; set; }
}
public class CheckListItem
{
    [PrimaryKey, AutoIncrement]
    public int CheckListItemID { get; set; }

    public string ItemText { get; set; }
    public bool isChecked { get; set; }
    public int ItemOrder { get; set; }

    public int CheckListID { get; set; }
}

As a side note, using EF is making your life much harder. It is better to follow Microsoft Recomendations and use sqlite-net-pcl per Maui documentation

huangapple
  • 本文由 发表于 2023年7月18日 02:24:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/76707166.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定