You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

sqlite-net-pcl库是否支持一对多、多对多关系?Xamarin.Forms新手求助

嘿,刚上手Xamarin.Forms和sqlite-net-pcl的话,你的问题确实是新手常问的——我来给你掰扯清楚:

sqlite-net-pcl的关系支持情况

首先明确两个核心点:

  • 一对多关系:sqlite-net-pcl原生支持,只需要手动定义外键和导航属性就能实现
  • 多对多关系:它没有内置的自动映射支持,需要你手动创建中间关联表来处理
一对多关系的实现步骤(以分类&产品为例)

下面用「分类(Category)→ 多个产品(Product)」的典型场景,一步步演示具体操作:

1. 定义实体类

先创建两个实体,明确外键关联和内存中的导航属性:

public class Category
{
    // 主键,自动递增
    [PrimaryKey, AutoIncrement]
    public int Id { get; set; }
    public string Name { get; set; }

    // 导航属性:存储该分类下的所有产品
    // 加[Ignore]是因为这个属性不需要存入数据库,仅用于内存中关联数据
    [Ignore]
    public List<Product> Products { get; set; } = new List<Product>();
}

public class Product
{
    [PrimaryKey, AutoIncrement]
    public int Id { get; set; }
    public string Name { get; set; }

    // 外键:关联到Category的Id字段
    [ForeignKey(typeof(Category))]
    public int CategoryId { get; set; }

    // 导航属性:存储该产品所属的分类
    [Ignore]
    public Category Category { get; set; }
}

2. 初始化数据库连接

创建本地数据库文件并生成对应的数据表:

// 获取适配各平台的本地存储路径
var dbPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Shop.db3");
// 初始化异步连接(推荐用Async版本,避免阻塞UI线程)
var db = new SQLiteAsyncConnection(dbPath);

// 创建Category和Product两张表
await db.CreateTablesAsync<Category, Product>();

// 可选:开启SQLite外键约束,支持级联删除/更新等操作
await db.ExecuteAsync("PRAGMA foreign_keys = ON;");

3. 插入关联数据

先插入父实体(分类),再插入子实体(产品)并绑定外键:

// 先插入一个分类
var electronicsCategory = new Category { Name = "电子产品" };
await db.InsertAsync(electronicsCategory);

// 插入属于该分类的两个产品,指定CategoryId为刚插入的分类ID
var phone = new Product { Name = "智能手机", CategoryId = electronicsCategory.Id };
var laptop = new Product { Name = "笔记本电脑", CategoryId = electronicsCategory.Id };

await db.InsertAllAsync(new List<Product> { phone, laptop });

4. 查询关联数据

sqlite-net-pcl原生不会自动加载关联数据,需要手动查询并绑定到导航属性:

// 第一步:查询目标分类
var targetCategory = await db.Table<Category>()
    .FirstOrDefaultAsync(c => c.Name == "电子产品");

// 第二步:查询该分类下的所有产品,赋值给导航属性
if (targetCategory != null)
{
    targetCategory.Products = await db.Table<Product>()
        .Where(p => p.CategoryId == targetCategory.Id)
        .ToListAsync();
}

// 现在targetCategory.Products里就包含所有关联的产品了

如果觉得手动查询太繁琐,可以安装sqlite-net-extensions扩展包,它提供了GetWithChildrenAsync这类方法能自动加载关联数据——不过这属于额外扩展,原生sqlite-net-pcl还是需要手动处理。

5. 处理更新/删除

如果开启了外键约束,你可以在创表时指定级联操作,比如删除分类时自动删除所有关联产品:

// 用自定义SQL语句创表(代替CreateTablesAsync),添加级联删除约束
await db.ExecuteAsync(@"CREATE TABLE IF NOT EXISTS Product (
    Id INTEGER PRIMARY KEY AUTOINCREMENT,
    Name TEXT,
    CategoryId INTEGER,
    FOREIGN KEY (CategoryId) REFERENCES Category(Id) ON DELETE CASCADE
)");

// 之后删除分类时,所有关联的产品会被自动删除
await db.DeleteAsync(electronicsCategory);
关于多对多关系的补充

比如「学生(Student)→ 多门课程(Course)」的多对多场景,你需要创建一个中间表StudentCourse来存储关联关系:

public class StudentCourse
{
    [PrimaryKey, AutoIncrement]
    public int Id { get; set; }
    [ForeignKey(typeof(Student))]
    public int StudentId { get; set; }
    [ForeignKey(typeof(Course))]
    public int CourseId { get; set; }
}

查询时,先通过中间表找到关联的ID,再查询对应的实体,逻辑和一对多类似,只是多了一步中间表的查询操作。

内容的提问来源于stack exchange,提问作者Md Tayeb Himel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:10:57