Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >如何处理EF Core的多对多关系?

如何处理EF Core的多对多关系?

作者头像
沙漠尽头的狼
发布于 2021-12-01 07:31:44
发布于 2021-12-01 07:31:44
3.6K00
代码可运行
举报
文章被收录于专栏:Dotnet9Dotnet9
运行总次数:0
代码可运行

多对多关系不像其他关系那么简单,在这篇文章中,我将向您展示如何创建多对多关系以及如何在 EF Core 中使用它们。

模型

多对多的简单而实用的例子可能是某种数字电子商务商店。用户可以将商品放入购物车(一个购物车可以有多个商品),而商品属于多个购物车。让我们从创建CartItem类开始。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Cart
{
    public int Id { get; set; }

    public ICollection<Item> Items { get; set; }
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Item
{
    public int Id { get; set; }

    public string Name { get; set; }

    public int Quantity { get; set; }

    public ICollection<Cart> Carts { get; set; }
}

这看起来不错,但它不起作用。在本文发表时,EF Core 无法处理这种情况。看起来EF Core不知道如何处理这种关系,当您尝试添加迁移时,您会得到以下结果:

Unable to determine the relationship represented by navigation property ‘Cart.Items’ of type ‘ICollection’. Either manually configure the relationship, or ignore this property using the ‘[NotMapped]’ attribute or by using ‘EntityTypeBuilder.Ignore’ in ‘OnModelCreating’. 【无法确定类型为“ICollection<Item>”的导航属性“Cart.Items”表示的关系。手动配置关系,或使用“[NotMapped]”属性或使用“OnModelCreating”中的“EntityTypeBuilder.Ignore”忽略此属性。】

我们需要做的第一件事是手动创建另一个“中间”类(表),它将建立CartItem的多对多关系,让我们创建这个类:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class CartItem
{
    public int CartId { get; set; }
    public Cart Cart { get; set; }

    public int ItemId { get; set; }
    public Item Item { get; set; }
}

我们创建了关联CartItem的新类CartItem,我们还需要更改它们各自的导航属性:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Cart
{
    public int Id { get; set; }

    public ICollection<CartItem> Items { get; set; }
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Item
{
    public int Id { get; set; }

    public string Name { get; set; }

    public int Quantity { get; set; }

    public ICollection<CartItem> Carts { get; set; }
}

如果您现在尝试添加迁移,则会出现另一个错误:

The entity type ‘CartItem’ requires a primary key to be defined. 【实体类型“CartItem”需要定义一个主键。】

对,CartItem没有主键, 由于它是多对多关系,因此它应该具有复合主键。复合主键类似于常规主键,但它由两个属性(列)而不是一个属性组成。目前,创建复合键的唯一方法是在OnModelCreating.

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
protected override void OnModelCreating(ModelBuilder builder)
{
    base.OnModelCreating(builder);

    builder.Entity<CartItem>().HasKey(i => new { i.CartId, i.ItemId });
}

最后,我们的数据库结构可以由 EntityFramework 处理,我们可以继续迁移了。

插入多对多

假设我们已经有CartItem在我们的数据库中,现在我们想将特定商品(Item)添加到特定购物车(Cart),为了做到这一点,我们需要创建新的CartItem并保存它。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var cart = db.Carts.First(i => i.Id == 256);
var item = db.Items.First(i => i.Id == 1024);

// 可以使用两个类的主键ID进行关联
var cartItem = new CartItem
{
    CartId = cart.Id,
    ItemId = item.Id
};

// 也可以使用两个类实体进行关联
var cartItem = new CartItem
{
    Cart = cart,
    Item = item
};

db.Add(cartItem);
db.SaveChanges();

在多对多中检索相关数据

从数据库中获取数据相当简单,注意使用Include关联检索相关数据。这里总共涉及3个表:Cart, Item, CartItem(将商品Item与购物车Cart关联起来)。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 获取关联所有商品的指定购物车
var cartIncludingItems = db.Carts.Include(cart => cart.Items).ThenInclude(row => row.Item).First(cart => cart.Id == 1);
// 获取指定购物车的所有商品
var cartItems = cartIncludingItems.Items.Select(row => row.Item);

另外,有些操作可以不使用关系来执行。例如,如果您有购物车ID,则可以使用以下 Linq 一次获取所有商品:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var cartId = 1;
var cartItems = db.Items.Where(item => item.Carts.Any(j => j.CartId == cartId));

相同的原则适用于相反的用例,这意味着您可以应用上述模式来获取具有特定项目的所有购物车。

从多对多中删除

删除是指删除购物车Cart和商品Item之间的关系CartItem。在以下示例中,我们不会删除购物车Cart或商品Item,只会删除购物车Cart和商品Item之间的关系CartItem

让我们从购物车Cart中删除单个产品Item开始。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var cartId = 1;
var itemId = 1;
var cartItem = db.CartsItems.First(row => row.CartId == cartId && row.ItemId == itemId);

db.Remove(cartItem);
db.SaveChanges();

然后,让我向您展示如何从购物车中删除所有项目。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var cart = db.Carts.Include(c=> c.Items).First(i => i.Id == 2);

db.RemoveRange(cart.Items);
db.SaveChanges();
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-11-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Dotnet9 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
EF Core如何处理多对多关系
EF Core在处理多对多关系时并不像一对一和一对多关系那样好处理,下面我们利用一个简单的电子商城购物车来讲解一下吧。
喵叔
2021/11/24
2.5K0
如何一步一步用DDD设计一个电商网站(四)—— 把商品卖给用户
上篇中我们讲述了“把商品卖给用户”中的商品和用户的初步设计。现在把剩余的“卖”这个动作给做了。这里提醒一下,正常情况下,我们的每一步业务设计都需要和领域专家进行沟通,尽可能的符合通用语言的表述。这里的领域专家包括但不限于当前开发团队中对这块业务最了解的开发人员、系统实际的使用人等。
Zachary_ZF
2018/09/10
9740
如何一步一步用DDD设计一个电商网站(四)—— 把商品卖给用户
C#/.NET/.NET Core开发实战
在本文中,我们将通过一个实战项目来展示如何使用C#、.NET和.NET Core来构建一个简单的电子商务平台。这个项目将涵盖后端API的开发、数据库设计、以及前端页面的基本呈现。
Michel_Rolle
2024/10/09
3.4K0
实战丨云开发商城小程序(附源码)
* 本文包含较多代码片段,PC端浏览推荐前往:https://cloud.tencent.com/document/product/876/70253
腾讯云开发TCB
2022/03/10
7K0
实战丨云开发商城小程序(附源码)
初探领域驱动设计(1)为复杂业务而生
概述   领域驱动设计也就是3D(Domain-Driven Design)已经有了10年的历史,我相信很多人或多或少都听说过这个名词,但是有多少人真正懂得如何去运用它,或者把它运用好呢?于是有人说,DDD和TDD这些玩意是一些形而上的东西,只是一茶余饭后的谈资,又或是放到简历上提升逼格而已。前面这句话我写完之后犹豫了,犹豫要不要把它删掉,因为它让我看起来像个喷子,我确实感到不解,为什么别人10年前创造总结出来的东西,我们在10年之后对它的理解还处于这么低的一个层次。开篇就说远了,我也是最近才开始认真学习领
用户1153966
2018/03/14
1.1K0
初探领域驱动设计(1)为复杂业务而生
Java 20 的新功能入门
Java是一种广泛应用于软件开发的编程语言,自诞生以来不断演进和改进。每个新版本都引入了一些新的功能和改进,帮助开发者更轻松地构建可靠的和高效的应用程序。 在本篇博客文章中,我们将重点介绍Java 20中引入的新功能,帮助读者了解并入门这些新特性。
大盘鸡拌面
2023/11/02
2990
如何一步一步用DDD设计一个电商网站(十)—— 一个完整的购物车
之前的文章中已经涉及到了购买商品加入购物车,购物车内购物项的金额计算等功能。本篇准备把剩下的购物车的基本概念一次处理完。
Zachary_ZF
2018/09/10
9110
如何一步一步用DDD设计一个电商网站(十)—— 一个完整的购物车
【愚公系列】2022年01月 Django商城项目 30-购物车功能实现
文章目录 一、添加购物车 1.后端逻辑代码 2.前台请求接口代码 3.实际效果 二、获取购物车 1.后端逻辑代码 2.前台页面代码 3.实际效果 三、更新购物车 1.后端逻辑代码 2.前台页面代码 3.实际效果 四、删除购物车 1.后端逻辑代码 2.前台页面代码 五、合并购物车 一、添加购物车 1.后端逻辑代码 """ 一 前后端需求分析需求 前端需要收集: 商品id,商品数量, 选中是可选的(默认就是选中) 如果用户登陆了则请求携带session id
愚公搬代码
2022/02/04
6380
【愚公系列】2022年01月 Django商城项目 30-购物车功能实现
【Vue H5项目实战】从0到1的肯德基点餐系统—— 商品与购物车逻辑设计(Vue3.2 + Vite + TS + Vant + Pinia + Nodejs
文章链接:https://cloud.tencent.com/developer/article/2473693
中杯可乐多加冰
2024/12/04
4270
Java Web 项目在线商城开发教程
在线商城是电子商务的重要载体,基于Java Web技术开发的在线商城,具有跨平台性、稳定性和强大的生态系统支持等优势。它能为用户提供便捷的购物体验,同时为商家提供高效的商品管理和订单处理平台。
啦啦啦191
2025/08/03
1030
Java Web 项目在线商城开发教程
Web 小案例 -- 网上书城(三)
内容有点乱,有兴趣的同伙可依照后面的案例结构结合文章进行阅读    和网上购买东西一样,你可以在不登录的状态下去浏览商品,但是当你想把自己中意的东西加入购物车或是收藏起来就需要你拥有自己的账号然后登录后才可以进一步操作,上次我们的翻页操作也就是可以供大家进行商品的浏览,所以这次我们先完成登录操作(具体登录所需我们直接插入数据表,不再对注册做处理)。 关于登录操作的具体操作步骤 向数据表 userinfo 中插入数据(user_id,user_name,Account_id) 在翻页操作页面我们已经将登录的超
bgZyy
2018/05/16
2.5K0
Go 语言代码简单的在线购物平台:
这个代码示例实现了一个简单的在线购物平台,包括用户、产品、购物车和订单的结构体,以及添加用户、产品、创建购物车、添加产品到购物车、提交订单和显示订单的方法。示例中展示了用户在购物平台上选购产品、添加到购物车、提交订单,并打印出订单的详情。希望这个示例能够对您提供一些参考!如果您还有其他问题,请随时提问。
青灯古酒
2023/10/16
4130
Web-第二十二天 Web商城实战二【悟空教程】
`cname` varchar(20) DEFAULT NULL, #分类名称
Java帮帮
2018/07/27
1.3K0
Web-第二十二天 Web商城实战二【悟空教程】
jsp电子商务购物车之四 数据库存储篇
为了方便用户下次登录,仍然可以看到自己的购物车内容,所以,需要在数据库存储相应的购物车项目,本处增加购物车项表;uid和bid是复合主键。
张哥编程
2024/12/17
3360
jsp电子商务购物车之四 数据库存储篇
VUE实现一个购物车
想象每个组件都分别为家中的成员:爸爸、妈妈、孩子们。但是,作为一个家庭,他们需要共享状态。在这个家庭中,充当看家狗的Vuex就是来帮助我们解决问题的。
HelloWorldZ
2024/03/20
2680
VUE实现一个购物车
购物车设计与实现
购物车是电商项目常用的功能,传统的做法可以使用关系型数据库,比如mysql来处理。但在实际使用中,由于购物车的数据量太大,而且修改频繁,会导致数据库的压力增加,所以一般不会直接使用关系型数据库来存储购物车信息。
用户3467126
2022/04/28
1.9K0
购物车设计与实现
深入解析Java中如何用Redis存储购物车信息:原理与实战案例
咦咦咦,各位小可爱,我是你们的好伙伴——bug菌,今天又来给大家普及Java SE相关知识点了,别躲起来啊,听我讲干货还不快点赞,赞多了我就有动力讲得更嗨啦!所以呀,养成先点赞后阅读的好习惯,别被干货淹没了哦~
bug菌
2024/10/24
4640
深入解析Java中如何用Redis存储购物车信息:原理与实战案例
学习PetShop3.0(4)购物车
终于到购物车了,在看这个之前应该已经明白了第三篇的那个模型,这样购物车基本也就明白了。 来看一下ShoppingCart.aspx这个页。 当你看好了一个宠物,比如可爱的Golden Retriever,嘿嘿,那就点add to cart按钮,这时就会跳到ShoppingCart.aspx,url里带了这个宠物的id号,根据该id号程序将该宠物放到cart里面。然后你可以再去挑别的宠物,比如一只猫(……),虽然这不是什么好主意。然后该宠物的id号又会被传到ShoppingCart.aspx,并添加到cart里面。在ShoppingCart.aspx里,你可以更改想要领养的宠物的数量,然后程序会根据你要求的数量来计算所需的钱以及该宠物是否还有剩余。在你做出决定后可以点proceed to checkout进入定单生成的环节。 上面是大体的流程。下面来看.net petshop是怎么实现这个cart的 基本的实现主要是BLL里的Cart和Model里的CartItemInfo,而Web.ProcessFlow的CartControler则负责具体的实现。想一想第三篇里的那个模型,具体到这里,每挑选一个宠物,就有一个CartItemInfo通过CartControler添加到了保存在Session里的Cart里面,最后生成定单的时候就从Session里把Cart的值取出来(CartControler有生成定单的方法,下一篇再说)。 来看一下ShoppingCart.aspx.cs里向Cart添加CartItemInfo的代码 // Create an instance of the cart controller ProcessFlow.CartController cartController = new ProcessFlow.CartController();
全栈程序员站长
2022/11/03
2750
Spring高级技术应用——百战商城实现(下)
需要用到pojo,但是我们可以通过依赖Mapper项目来简介添加Pojo项目 需要用到Spring Data整合Solr的坐标
时间静止不是简史
2020/07/27
1.3K0
Spring高级技术应用——百战商城实现(下)
商城业务:购物车
- 用户可以在未登录状态下将商品添加到购物车【游客购物车/离线购物车/临时购物车】
一个风轻云淡
2023/10/15
4090
商城业务:购物车
推荐阅读
相关推荐
EF Core如何处理多对多关系
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验