ASP.NET Core OData 实践——Lesson2查询和局部更新EntitySet(C#)

article/2025/6/30 7:00:42

大纲

  • 概念
  • 多态
  • 支持的接口
  • 主要模型设计(Models)
  • 控制器设计(ShapesController)
    • 数据源
    • 查询(GET)
      • 查询EntitySet中所有Entity
      • 查询EntitySet中所有Entity的个数
      • 查询EntitySet中派生类类型的Entity
      • 查询EntitySet中派生类类型的Entity的个数
    • 新增(POST)
      • 新增基类类型Entity
      • 新增派生类类型Entity
    • 完整更新(PUT)
    • 局部更新(PATCH)
      • 通过基类类型进行局部更新
      • 通过派生类类型进行局部更新
    • 删除(DELETE)
  • 主程序
    • 服务文档
    • 模型元文档
  • 代码地址
  • 参考资料

EntitySet 是 OData 数据模型的核心载体,它通过标准化的 HTTP 接口和查询协议,实现了实体集合的高效操作与灵活扩展。无论是简单的 CRUD 场景,还是复杂的多态查询与动态字段支持,EntitySet 都为构建可扩展、易维护的 RESTful 服务提供了坚实基础。通过理解 EntitySet 的工作机制,我们能更好地设计 OData 服务的资源结构,提升 API 的可用性与性能。

概念

EntitySet 可以理解为数据库中的一张表,或者说是某种实体类型(EntityType)的集合。在 OData 服务中,每个 EntitySet 都会映射到一个控制器(Controller),用于处理对该集合的各种操作(如查询、添加、更新、删除等)。

多态

在 OData(开放数据协议)中,EntitySet 对多态的支持是其数据模型灵活性的重要体现。通过多态机制,EntitySet 可以包含基类实体及其派生类实体,允许开发者在不修改服务端元数据的情况下,扩展实体类型的行为与属性。
举个例子:我们定义一个基类 Shape(包含 Id 和 Area 属性),其派生类 Circle(新增 Radius 属性)和 Rectangle(新增 Width、Height 属性),三者可共同存储在 Shapes 这个 EntitySet 中。

支持的接口

EntitySet自身不可以新增,只能向其新增Entity。
由于Put是完整更新,所以EntitySet没有该接口。但是可以更新部分的Entity(局部修改),所以可以有Patch接口。
同时EntitySet自身也不能删除,所以也没有DELETE接口。

Request MethodRoute Template说明
GET~/{entityset}查询实体集中所有Entity
GET~/{entityset}/$count查询实体集中所有Entity的个数
GET~/{entityset}/{cast}查询实体集中派生类类型所有Entity
GET~/{entityset}/{cast}/$count查询实体集中派生类类型所有Entity的个数
POST~/{entityset}向实体集中新增基类类型Entity
POST~/{entityset}/{cast}向实体集中新增派生类类型Entity
PATCH~/{entityset}局部更新实体集中基类类型Entity
PATCH~/{entityset}/{cast}局部更新实体集中派生类类型Entityy

主要模型设计(Models)

  • Shape:基础形状类,包含 Id 和 Area 属性。
  • Circle:继承自 Shape,增加 Radius 属性。
  • Rectangle:继承自 Shape,增加 Length 和 Width 属性。

这种设计体现了面向对象的继承关系,方便在 OData 查询和操作时支持多态。
我们在工程中新增Models目录,并添加Shape、Circle和Rectangle类文件。
在这里插入图片描述
对应文件填入以下内容:

namespace Lesson2.Models
{public class Shape{public int Id { get; set; }public double Area { get; set; }}
}
namespace Lesson2.Models
{public class Circle : Shape{public double Radius { get; set; }}
}
namespace Lesson2.Models
{public class Rectangle : Shape{public double Length { get; set; }public double Width { get; set; }}
}

控制器设计(ShapesController)

在项目下新建Controller目录,其下新增一个ShapesController类。该类注册于ODataController,以便拥有如下能力:

  1. OData 路由支持
    继承 ODataController 后,控制器自动支持 OData 路由(如 /odata/Shapes(1)),可以直接响应 OData 标准的 URL 路径和操作。
  2. OData 查询参数支持
    可以使用 [EnableQuery] 特性,自动支持 $filter、$select、$orderby、$expand 等 OData 查询参数,无需手动解析。
  3. OData 响应格式
    返回的数据会自动序列化为 OData 标准格式(如 JSON OData),方便前端或其他系统消费。
  4. OData Delta 支持
    支持 Delta<T>、DeltaSet<T> 等类型,便于实现 PATCH、批量 PATCH 等 OData 特有的部分更新操作。
  5. 更丰富的 OData 语义
    继承后可方便实现实体集、实体、导航属性、复杂类型等 OData 语义,提升 API 的表达能力。
    在这里插入图片描述
using Lesson2.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.OData.Deltas;
using Microsoft.AspNetCore.OData.Query;
using Microsoft.AspNetCore.OData.Routing.Controllers;
using System.Reflection;namespace Lesson2.Controllers
{public class ShapesController : ODataController{……}
}

下面我们将在ShapesController 内填充代码

数据源

 private static List<Shape> shapes =[new Shape { Id = 1, Area = 28 },new Circle { Id = 2, Radius = 3.5, Area = 38.5 },new Rectangle { Id = 3, Length = 8, Width = 5, Area = 40 }];

使用静态 List 存储所有形状对象,便于演示和测试。

查询(GET)

Request MethodRoute Template说明
GET~/{entityset}查询实体集中所有Entity
GET~/{entityset}/$count查询实体集中Entity的个数
GET~/{entityset}/{cast}查询实体集中派生类类型的Entity
GET~/{entityset}/{cast}/$count查询实体集中派生类类型所有Entity的个数

在下面的接口代码中,我们使用了Ok()方法。在正常情况下,也可以直接返回结果(return shapes),HTTP Response的内容和加了Ok方法(return Ok(shapes))一样,但是这依赖于框架的推导。这就导致某些情况下(如返回 null),没有加Ok()方法可能不会让框架自动包装为 404 或 204,易引发不一致的响应,所以强烈建议使用Ok方法。

我们还使用[EnableQuery]修饰了每个查询方法。这是因为这个特性让OData 控制器方法自动支持 OData 查询参数,如 $count、 $filter、$select、$orderby、$top、$skip 等。因为我们在实例中需要查询数量($count),所以使用了该修饰符。

查询EntitySet中所有Entity

Request MethodRoute Template说明
GET~/{entityset}查询实体集中所有Entity
[EnableQuery]
public ActionResult<IEnumerable<Shape>> Get()
{return Ok(shapes);
}

上述代码等同于

[EnableQuery]
public ActionResult<IEnumerable<Shape>> GetFromShape()
{return Ok(shapes.OfType<Shape>().ToList());
}
  • Request

下面请求对应于ActionResult<IEnumerable<Shape>> Get()

curl --location 'http://localhost:5119/odata/Shapes'

下面请求对应于ActionResult<IEnumerable<Shape>> GetFromShape()

curl --location 'http://localhost:5119/odata/Shapes/Lesson2.Models.Shape'
  • Response

它们返回的数据是一样

{"@odata.context": "http://localhost:5119/odata/$metadata#Shapes","value": [{"Id": 1,"Area": 28.0},{"@odata.type": "#Lesson2.Models.Circle","Id": 2,"Area": 38.5,"Radius": 3.5},{"@odata.type": "#Lesson2.Models.Rectangle","Id": 3,"Area": 40.0,"Length": 8.0,"Width": 5.0}]
}

查询EntitySet中所有Entity的个数

Request MethodRoute Template说明
GET~/{entityset}/$count查询实体集中所有Entity的个数
  • Request
curl --location 'http://localhost:5119/odata/Shapes/$count'
  • Response
3

查询EntitySet中派生类类型的Entity

Request MethodRoute Template说明
GET~/{entityset}/{cast}查询实体集中派生类类型所有Entity

以查询Rectangle的EntitySet为例。

[EnableQuery]
public ActionResult<IEnumerable<Rectangle>> GetFromRectangle()
{return Ok(shapes.OfType<Rectangle>().ToList());
}
  • Request
curl --location 'http://localhost:5119/odata/Shapes/Lesson2.Models.Rectangle'
  • Response
{"@odata.context": "http://localhost:5119/odata/$metadata#Shapes/Lesson2.Models.Rectangle","value": [{"Id": 3,"Area": 40.0,"Length": 8.0,"Width": 5.0}]
}

查询EntitySet中派生类类型的Entity的个数

Request MethodRoute Template说明
GET~/{entityset}/{cast}/$count查询实体集中派生类类型所有Entity的个数
  • Request
curl --location 'http://localhost:5119/odata/Shapes/Lesson2.Models.Rectangle/$count'
  • Response
1

新增(POST)

Request MethodRoute Template说明
POST~/{entityset}向实体集中新增基类类型Entity
POST~/{entityset}/{cast}向实体集中新增派生类类型Entity

在下面接口的代码中,我们使用了Created() 方法。它的作用是用于在 Web API 控制器中返回 HTTP 201 Created 响应,表示资源已被成功创建。它还会在响应体中包含新创建Entity(如 shape、circle、rectangle),并且会自动设置响应头中的 Location,指向新资源的 URI,方便客户端后续访问。

新增基类类型Entity

Request MethodRoute Template说明
POST~/{entityset}向实体集中新增基类类型Entity

添加一个 Shape类对象到集合。需要注意的是:不能通过此新增子类(Circle和Rectangle)对象。

public ActionResult Post([FromBody] Shape shape)
{shapes.Add(shape);return Created(shape);
}
  • Request
    对基类类型的访问对应的路径是~/{entityset}
curl --location 'http://localhost:5119/odata/Shapes' \
--header 'Content-Type: application/json' \
--data '{"Id": 4,"Area": 36
}'
  • Response
{"@odata.context": "http://localhost:5119/odata/$metadata#Shapes/$entity","Id": 4,"Area": 36.0
}

新增派生类类型Entity

Request MethodRoute Template说明
POST~/{entityset}/{cast}向实体集中新增派生类类型Entity

我们有两个子类:Circle和Rectangle。本例我们以Circle为例,添加一个Circle对象。

public ActionResult PostFromCircle([FromBody] Circle circle)
{shapes.Add(circle);return Created(circle);
}
  • Request
    对派生类类型的访问路径是~/{entityset}/{cast}
curl --location 'http://localhost:5119/odata/Shapes/Lesson2.Models.Circle' \
--header 'Content-Type: application/json' \
--data '{"Id": 5,"Radius": 1.4,"Area": 6.16
}'
  • Response
{"@odata.context": "http://localhost:5119/odata/$metadata#Shapes/Lesson2.Models.Circle/$entity","Id": 5,"Area": 6.16,"Radius": 1.4
}

完整更新(PUT)

OData 标准中,EntitySet(实体集)不支持直接对整个集合使用 PUT 方法。

局部更新(PATCH)

Put和Patch都是更新,但是Put是整体更新,Patch是局部更新。
对于EntitySet,Patch请求会更新其中一些Entity的数据。

Request MethodRoute Template说明
PATCH~/{entityset}局部更新实体集中基类类型Entity
PATCH~/{entityset}/{cast}局部更新实体集中派生类类型Entityy

通过基类类型进行局部更新

Request MethodRoute Template说明
PATCH~/{entityset}局部更新实体集中基类类型Entity
public ActionResult Patch([FromBody] DeltaSet<Shape> deltaSet)
{if (deltaSet == null){return BadRequest();}foreach (Delta<Shape> delta in deltaSet){if (delta.TryGetPropertyValue("Id", out object idAsObject)){var shape = shapes.SingleOrDefault(d => d.Id.Equals(idAsObject));if (shape == null){return NotFound();}else if (!shape.GetType().Equals(delta.StructuredType)){return BadRequest();}delta.Patch(shape);}}return Ok();
}
  • Request
curl --location --request PATCH 'http://localhost:5119/odata/Shapes' \
--header 'Content-Type: application/json' \
--data-raw '{"value": [{"Id": 1,"Area": 2},{"@odata.type": "#Lesson2.Models.Circle","Id": 2,"Radius": 0.7,"Area": 1.54},{"@odata.type": "#Lesson2.Models.Rectangle","Id": 3,"Length": 8,"Width": 4,"Area": 32}]
}
'

由于只有Id为1的Entity是基类类型,其对应的数据不用@odata.type描述;其他的非基类类型的Entity都需要声明类型。

通过派生类类型进行局部更新

Request MethodRoute Template说明
PATCH~/{entityset}/{cast}局部更新实体集中派生类类型Entityy
public ActionResult PatchFromRectangle([FromBody] DeltaSet<Rectangle> deltaSet)
{if (deltaSet == null){return BadRequest();}foreach (Delta<Rectangle> delta in deltaSet){if (delta.TryGetPropertyValue("Id", out object idAsObject)){var rectangle = shapes.SingleOrDefault(d => d.Id.Equals(idAsObject)) as Rectangle;if (rectangle == null) // Ensure rectangle is not null before calling Patch{return NotFound();}delta.Patch(rectangle);}}return Ok();
}
  • Request
curl --location --request PATCH 'http://localhost:5119/odata/Shapes/Lesson2.Models.Rectangle' \
--header 'Content-Type: application/json' \
--data '{"value": [{"Id": 3,"Length": 8,"Width": 4,"Area": 32}]
}'

由于URI路径中已经包含了特定派生类的名称,其和我们要Patch的数据的类型一致,于是负载中就不用增加@odata.type描述。

删除(DELETE)

在 OData 标准中,EntitySet(实体集)不支持直接对整个集合使用 DELETE 方法。

主程序

我们只用将基类类型注册为EntitySet,而不用注册其派生类类型。

using Lesson2.Models;
using Microsoft.AspNetCore.OData;
using Microsoft.OData.ModelBuilder;
using Microsoft.OData.Edm;var builder = WebApplication.CreateBuilder(args);// 提取 OData EDM 模型构建为方法,便于维护和扩展
static IEdmModel GetEdmModel()
{var modelBuilder = new ODataConventionModelBuilder();modelBuilder.EntitySet<Shape>("Shapes");return modelBuilder.GetEdmModel();
}// 添加 OData 服务和配置
builder.Services.AddControllers().AddOData(options =>options.Select().Filter().OrderBy().Expand().Count().SetMaxTop(null).AddRouteComponents("odata", GetEdmModel())
);var app = builder.Build();app.UseRouting();app.MapControllers();app.Run();

服务文档

  • Request
curl --location 'http://localhost:5119/odata'
  • Response
{"@odata.context": "http://localhost:5119/odata/$metadata","value": [{"name": "Shapes","kind": "EntitySet","url": "Shapes"}]
}

模型元文档

  • Request
curl --location 'http://localhost:5119/odata/$metadata'
  • Response
<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx"><edmx:DataServices><Schema Namespace="Lesson2.Models" xmlns="http://docs.oasis-open.org/odata/ns/edm"><EntityType Name="Shape"><Key><PropertyRef Name="Id" /></Key><Property Name="Id" Type="Edm.Int32" Nullable="false" /><Property Name="Area" Type="Edm.Double" Nullable="false" /></EntityType><EntityType Name="Circle" BaseType="Lesson2.Models.Shape"><Property Name="Radius" Type="Edm.Double" Nullable="false" /></EntityType><EntityType Name="Rectangle" BaseType="Lesson2.Models.Shape"><Property Name="Length" Type="Edm.Double" Nullable="false" /><Property Name="Width" Type="Edm.Double" Nullable="false" /></EntityType></Schema><Schema Namespace="Default" xmlns="http://docs.oasis-open.org/odata/ns/edm"><EntityContainer Name="Container"><EntitySet Name="Shapes" EntityType="Lesson2.Models.Shape" /></EntityContainer></Schema></edmx:DataServices>
</edmx:Edmx>

它包含如下几部分:

  1. 实体类型定义
  • Shape
    • EntityType Name=“Shape”:定义了一个名为 Shape 的实体类型。
    • <Key><PropertyRef Name=“Id” /></Key>:以 Id 属性作为主键。
    • <Property Name=“Id” Type=“Edm.Int32” Nullable=“false” />:Id 是 int 类型,不能为空。
    • <Property Name=“Area” Type=“Edm.Double” Nullable=“false” />:Area 是 double 类型,不能为空。
  • Circle
    • EntityType Name=“Circle” BaseType=“Lesson2.Models.Shape”:Circle 继承自 Shape。
    • <Property Name=“Radius” Type=“Edm.Double” Nullable=“false” />:新增属性 Radius,double 类型,不能为空。
  • Rectangle
    • EntityType Name=“Rectangle” BaseType=“Lesson2.Models.Shape”:Rectangle 继承自 Shape。
    • <Property Name=“Length” Type=“Edm.Double” Nullable=“false” />:新增属性 Length,double 类型,不能为空。
    • <Property Name=“Width” Type=“Edm.Double” Nullable=“false” />:新增属性 Width,double 类型,不能为空。
  1. 实体容器与实体集
  • EntityContainer Name=“Container”:定义了一个实体容器,OData 服务的入口。
  • <EntitySet Name=“Shapes” EntityType=“Lesson2.Models.Shape” />:定义了一个名为 Shapes 的实体集,类型为 Shape。
    这意味着可以通过 /odata/Shapes 路由访问所有 Shape 及其派生类(Circle、Rectangle)对象。
  1. 继承关系
  • Circle 和 Rectangle 都通过 BaseType 继承自 Shape,拥有 Shape 的所有属性,并扩展了自己的属性。

代码地址

https://github.com/f304646673/odata/tree/main/csharp/Lesson/Lesson2

参考资料

  • https://learn.microsoft.com/en-us/odata/webapi-8/fundamentals/entity-routing?tabs=net60%2Cvisual-studio

http://www.hkcw.cn/article/yEsndSxsWh.shtml

相关文章

工业智能网关提升铁合金工厂远程运维效率的实践应用

一、项目背景 铁合金行业作为国民经济基础原材料产业&#xff0c;在钢铁、机械制造等众多领域有着广泛应用&#xff0c;其生产规模庞大且呈持续增长趋势。然而&#xff0c;传统的铁合金生产监控方式存在诸多弊端&#xff0c;如数据采集不及时、不准确&#xff0c;信息孤岛现象…

高敏感是一种天赋吗 被低估的感知力

今天是周三,人民日报夜读栏目的“周三加油站”如约而至。我们想聊聊“高敏感”这件事。听觉敏感的人晚上睡觉时容易被细小的声音吵醒,嗅觉灵敏的人能轻易闻到不易察觉的气味,触觉上高度敏感的人在别人靠近时常常感到紧张。对旁人情绪变化敏感的人则习惯性推敲别人的言外之意…

婚内强奸案男子看守所里与妻协议离婚 证据不足获释求赔偿

5月29日下午,40岁的尹某在律师陪同下向河南省濮阳县人民检察院递交了《国家赔偿申请书》,请求国家赔偿33万元,并要求追究相关办案人员的责任。此前,尹某因“婚内强奸”被关押了285天。尹某提到,在他被关押之前,妻子曾两次提起离婚诉讼但均被法院驳回。去年4月,当他还在看…

端午出行热度攀升释放消费新活力 粽行山海成潮流

交通运输部最新数据显示,2025年端午假期全社会跨区域人员流动量预计达6.87亿人次,较2024年同期增长7.7%。高速公路日均流量突破4070万辆次,其中新能源汽车占比显著提升至21%,反映出我国交通出行结构的深刻变革。节日叠加效应成为出行增长的核心驱动力。端午假期与“六一”儿…

电影《坪石先生》入围上影节创投 致敬教育救国精神

第二十七届上海国际电影节电影项目创投近日公布入围名单,讲述抗战时期岭南先贤故事的粤产电影《坪石先生》入围制作中项目单元。该片以抗战时期中山大学西迁办学的真实历史为背景,聚焦民国教育大家黄际遇、卫梓松、杜定友等“坪石先生”,讲述他们在战火中坚守教育阵地、延续…

划龙舟的风还是吹到北京来了 北运河上演速度与激情

5月31日上午9点,2025年北京端午节龙舟大赛将在北运河东关大桥至上营大桥水域拉开帷幕。此次赛事吸引了全国30多支龙舟队伍和近500名运动员参加,市民和游客可以免费观看比赛。参赛的龙舟队已经在北运河进行适应性训练。端午节假期期间,北运河水域将举办一系列水上和岸上活动,…

7.3 Organizing data into training batches

Chapter 7-Fine-tuning to follow instructions 7.3 Organizing data into training batches 下一步是构建训练批次 ​ 定义一种方法&#xff0c;以确保我们的模型在微调过程中接收格式化的训练数据。如下图所示&#xff0c;我们通过几个步骤处理此数据集批处理。 ​ 首先&…

AI数字人系统开发——引领未来智能交互潮流

在智能交互的时代&#xff0c;AI数字人系统开发正以其独特的魅力和巨大的潜力&#xff0c;引领着未来的发展方向。它不仅改变了我们与机器的交互方式&#xff0c;还为我们带来了全新的生活和工作体验。 我们的AI数字人系统开发&#xff0c;以创新为驱动&#xff0c;不断追求技…

Langchain4j Function Calling (5)

Langchain4j Function Calling(函数调用) Function Calling 函数调用 也叫 Tools 工具. 不用函数调用存在的问题 测试计算问题 提供agent AiService(wiringMode AiServiceWiringMode.EXPLICIT,chatModel "qwenChatModel",chatMemory "chatMemory",ch…

《数字世界的连接器:计算机网络应用全景解析》

一、引言 在万物互联的今天&#xff0c;计算机网络早已不再是幕后基础设施&#xff0c;而是推动数字时代变革的“神经系统”。无论你在使用智能手机刷短视频&#xff0c;还是企业通过云服务部署系统&#xff0c;这一切都离不开计算机网络的广泛应用。 本文将全面系统地介绍计…

密云北庄镇首次发现凤头鹰 生态魅力再添新证

近日,北庄镇观鸟爱好者与生态工作人员在日常监测中惊喜发现国家二级保护鸟类凤头鹰的踪迹。这一发现不仅为密云区鸟类名录新增一员,更印证了北庄镇作为“观鸟小镇”的生态魅力。凤头鹰是中型猛禽,因头部具短羽冠而得名,常栖息于山地森林中,以蛙、蜥蜴、鼠类及小型鸟类为食…

清华回应17岁学生登顶珠峰保送清华 最年轻登顶者澄清

近日,有媒体报道称北京第八十中学17岁的学生李浩榕成为中国首位从北坡登顶珠峰的青少年,消息一度登上热搜。还有报道称他是“全球中学生第一人”。不过,根据国内其他媒体报道,河北16岁女孩丁禹琪在2020年曾从北坡成功登顶珠峰。西藏登山协会证实,在中国业余登山爱好者中,…

宁德时代董事长现身尊界S800发布会 强调电池安全与可靠

在5月30日的尊界S800发布会上,华为与江淮汽车联合推出了新款车型尊界S800。宁德时代董事长曾毓群也出席了发布会,并强调智能与豪华的基础在于安全,而电池是实现这一目标的关键。曾毓群提到,安全是新能源汽车的生命线。要达到极致的安全标准,需要关注材料和化学体系、基于3…

利物浦签24岁荷兰边卫弗林蓬 3500万解约金锁定强援

利物浦宣布签下24岁的荷兰边卫弗林蓬,支付了3500万解约金。弗林蓬此前效力于勒沃库森。罗马诺确认,前亚特兰大主教练加斯佩里尼将执教罗马,签约三年。沙特媒体OKAZ报道,C罗拒绝了所有沙特国内外俱乐部的报价,并指示团队停止一切转会谈判,表明他将在利雅得胜利继续职业生涯…

贿赂百名医生的药企违规费用已清缴 相关人员接受调查处理

近期,我们收到关于某药企涉嫌向医生输送商业贿赂的举报信。对此,我们高度重视,立即成立调查组,并会同相关部门展开调查核实工作。以下是调查处置进展情况。举报信涉及125名医疗机构人员,其中6人信息重复,1人信息不实,实际核实为118人,分布在36家医疗机构(举报信中提到…

白举纲 只要有舞台就一定会在 歌手的自我救赎

《歌手》第三期中,白举纲遗憾落榜。其实早有迹象,他将《海鸥》和《The End of the World》融合在一起,编曲非常用心。但问题恰恰出在这首歌上,选得太“用力”了,不够松弛。如果他选择一首更轻松、更符合自己气质的歌曲,结果可能会完全不同。例如,马嘉祺选唱的《我也曾想…

日本首相石破茂国际论坛官宣:坚持战后和平发展道路,不重蹈覆辙

华沙犹太人殉难纪念碑前,一位德国总理突然双膝跪地。这一跪,让世界记住了勃兰特的名字。同样的二战轴心国,日本政要的身影却频频出现在靖国神社。2025年5月29日,东京“亚洲的未来”论坛现场。石破茂面对各国代表,首次以首相身份提及“吸取战争教训”。他承诺日本将坚持和平…

做实验 搞锻炼 神二十乘组的端午节很忙碌

当粽叶的幽香在神州大地飘荡,太空家园中的神舟二十号航天员乘组也寻味而至,送来了太空祝福。截至目前,三名航天员陈冬、陈中瑞、王杰进驻中国空间站已经一个多月了,今天是他们在太空迎来的第一个中国传统节日。三位航天员的端午节怎么度过?出差这段时间他们有哪些新的感悟…

全球住房危机影响近30亿人 亟需全球协调行动

当地时间5月29日至30日,第二届联合国人居大会续会在肯尼亚首都内罗毕召开。超过1000名代表参会,共同探讨日益严峻的全球住房危机,希望通过讨论、协作与政策规划推动问题的有效解决。联合国人类住区规划署执行主任阿纳克劳迪娅罗斯巴赫指出,据估计,全球有超过28亿人住房条件…

存款利率跌破1% 分红型理财产品发行升温:资金流向低估值资产

5月初降准释放的1万亿长期资金,减少了银行对高成本同业负债的依赖。配合存款利率下调,银行可将更多低成本资金用于贷款投放,形成低息吸储-低息放贷的良性循环。银行股为代表的低估红利资产具有双重防御属性。沪深300价值指数通过“低估值”指标筛选样本,其中银行股占比高达…