Semantic Kernel 架构决策实录:为何 Entity Framework 不被采纳为 Vector Store 连接器(ADR 0051 深度解析)
【免费下载链接】semantic-kernelIntegrate cutting-edge LLM technology quickly and easily into your apps项目地址: https://gitcode.com/GitHub_Trending/se/semantic-kernel
本篇文章基于 Semantic Kernel 仓库中的架构决策记录(ADR)0051-entity-framework-as-connector.md 展开,完整还原一次关键的技术调研过程:Entity Framework 能否作为统一的 Vector Store(向量存储)连接器接入 Semantic Kernel。你将看到新版向量存储设计对连接器的六项硬性要求、EF 在集合创建、键管理、向量映射、测试、.NET 兼容性上的真实局限,以及最终"不引入 EF 连接器、按数据库逐个添加连接器"这一决策背后的完整推理链条,同时结合仓库源码验证这一决策在后续版本中的落地形态。
决策背景:EF 的诱惑与新版 Vector Store 设计
为什么 Entity Framework 曾被认真考虑
Entity Framework 是 .NET(C#)生态中成熟的现代对象关系映射(ORM)框架,它允许开发者用统一的高层数据访问层,跨多种数据库构建整洁、可移植的数据层,包括 SQL Database(本地与 Azure)、SQLite、MySQL、PostgreSQL、Azure Cosmos DB 等,并原生支持 LINQ 查询、变更跟踪(change tracking)、更新与 Schema 迁移(migrations)。
对 Semantic Kernel 而言,EF 最诱人的价值在于多数据库支持:理论上,一个Entity Framework 连接器就能同时充当通往多种数据库的"枢纽",从而简化这些数据库集成的开发与维护成本。这正是 ADR 中"Context and Problem Statement"部分的核心问题:是否值得投入建设Microsoft.SemanticKernel.Connectors.EntityFramework?
新设计对连接器的要求(对应 ADR 0050)
在评估时,Semantic Kernel 正处于向量存储抽象从实验性IMemoryStore走向正式化设计的阶段(参见姊妹 ADR 0050-updated-vector-store-design.md)。新版设计中,集合管理与记录管理被拆分,核心接口为IVectorStoreRecordCollection<TKey, TRecord>,其中与数据库集合(collection/schema/table)打交道的四个方法是:
CollectionExistsAsync:判断集合是否存在CreateCollectionAsync:创建集合CreateCollectionIfNotExistsAsync:不存在则创建DeleteCollectionAsync:删除集合
这组方法要求连接器能够以编程方式、以统一语义管理集合的生命周期。而正是这一要求,与 Entity Framework 的现实能力产生了第一处冲突。
六大技术障碍逐项剖析
障碍一:集合创建(Collection Creation)没有跨数据库的统一抽象
在 Entity Framework 中,通过编程方式创建集合(即 Schema/Table)在生成环境是不被推荐的做法。官方推荐的两条路径是:
- Code-First:使用 Migrations(迁移)管理 Schema;
- Database-First:使用反向工程(Reverse Engineering,又称 scaffolding)从现有数据库生成模型。
编程式 Schema 创建仅被推荐用于测试/本地场景(参见EnsureCreated相关文档)。更麻烦的是,不同数据库的创建流程差异巨大。典型反例是MongoDB EF Core Provider:它既不支持 Schema 迁移,也不支持 database-first / model-first 模式,集合会在首次插入文档时自动创建(如果集合尚不存在)。
这意味着:IVectorStoreRecordCollection<TKey, TRecord>中的CreateCollectionAsync一族方法,在 EF 中找不到一套能覆盖大多数数据库的集合管理抽象。对这类场景,官方建议要么依赖自动创建机制,要么为每种数据库单独处理集合创建——例如 MongoDB 建议直接使用 MongoDB C# Driver。
结论:集合管理操作的跨数据库不一致,是 EF 无法契合新 Vector Store 设计的第一个硬伤。
障碍二:键管理(Key Management)无法统一
由于并非所有数据库都支持相同的键类型,EF 连接器不可能定义一套对所有数据库都有效的键类型集合。务实的选择是只支持标准类型(如string),再针对特定数据库做类型转换以符合其键约束。
但这恰恰抹掉了统一连接器的优势:键管理仍然要为每种数据库单独实现,等于把差异化工作从"数据库连接器层"搬回了"EF 连接器层",却没有换来任何抽象收益。
障碍三:向量类型ReadOnlyMemory<T>不受原生支持
这是最直接的技术阻断点。Semantic Kernel 绝大多数连接器使用ReadOnlyMemory<float>承载 Embedding 向量,而Entity Framework 开箱即用地不支持该类型。尝试映射时会产生如下运行时错误:
The property '{Property Name}' could not be mapped because it is of type 'ReadOnlyMemory<float>?', which is not a supported primitive type or a valid entity type. Either explicitly map this property, or ignore it using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.规避手段存在但不完美:可以改用byte[]类型,或编写显式类型映射来支持ReadOnlyMemory<T>。例如pgvector包已经这样做了(通过自定义VectorTypeMapping完成映射),但这种映射是否能在不同数据库上通用,并不明确——它很可能是数据库特定的。
障碍四:测试成本被严重低估
用 SQLite 编写 EF 连接器的单元/集成测试不能证明该集成在其他 EF 支持的数据库上可用。每个数据库都实现了一组属于自己的 EF 功能子集(feature set),因此为了保证连接器覆盖主流使用场景,必须针对每种数据库分别编写单元/集成测试。这意味着"一个连接器、一套测试"的规模效应并不成立,测试矩阵会成倍扩张。
障碍五:.NET 兼容性冲突
EF 的版本策略与 Semantic Kernel 的兼容性目标正面冲突:
- 无法使用最新版 Entity Framework Core 并同时面向 .NET Standard 开发;最后一个支持 .NET Standard 的 EF Core 版本是 5.0(评估时最新为 8.0)。因此 EF 连接器只能面向 .NET 8.0,而当时其他 SK 连接器同时面向
net8.0与netstandard2.0两个目标框架。 - 另一个选项是使用Entity Framework 6,它可以同时面向
net8.0与netstandard2.0,但 EF6已不再被积极开发,EF Core 提供的新特性不会再回填到 EF6 中。
两头不讨好:选 EF Core 牺牲兼容面,选 EF6 牺牲演进性。
障碍六:与既有 SK 数据库连接器的重叠
Semantic Kernel 已有多条数据库集成,且这些数据库同样被 EF 支持,于是产生三选一的局面:
| 方案 | 说明 | 代价 | | - | - | - | | EF 连接器 + 数据库连接器并存 | 同时维护Microsoft.SemanticKernel.Connectors.EntityFramework与Microsoft.SemanticKernel.Connectors.MongoDB等 | 两者必须产出完全一致的结果,需要补齐同一套单元/集成测试;任何逻辑修改都要同步到两个连接器 | | 只保留 EF 连接器 | 移除既有数据库连接器 | 对存量客户是破坏性变更;且需额外工作确保 EF 覆盖与旧连接器完全相同的功能面 | | 只保留数据库连接器 | 已有则无需额外工作;没有但重要则新增 | 若连接器尚不存在,需要单独实现 |
EF 与 SK 的数据库支持对照矩阵(核心表格)
以下表格来自 ADR 原文,仅列出支持向量搜索的数据库(注意:同一数据库引擎可能存在多个由不同厂商维护的 EF 集成,例如 MySQL 就有 Oracle 维护版与 Pomelo Foundation Project 维护版两个 EF NuGet 包):
| Database Engine | Maintainer / Vendor | Supported in EF | Supported in SK | Updated to SK memory v2 design | | - | - | - | - | - | | Azure Cosmos | Microsoft | Yes | Yes | Yes | | Azure SQL and SQL Server | Microsoft | Yes | Yes | No | | SQLite | Microsoft | Yes | Yes | No | | PostgreSQL | Npgsql Development Team | Yes | Yes | No | | MongoDB | MongoDB | Yes | Yes | No | | MySQL | Oracle | Yes | No | No | | Oracle DB | Oracle | Yes | No | No | | Google Cloud Spanner | Cloud Spanner Ecosystem | Yes | No | No |
此外,Semantic Kernel 额外支持的向量数据库连接器还包括:Azure AI Search、Chroma、Milvus、Pinecone、Qdrant、Redis、Weaviate。
这张表格揭示了一个关键事实:EF 支持的向量数据库,SK 几乎都已有(或即将有)原生连接器;EF 覆盖面中 SK 缺失的部分(MySQL、Oracle DB、Google Cloud Spanner)恰好是 SK 当前不提供向量连接器的数据库。
决策选项与最终结论
ADR 给出了两个候选方案:
- 新增
Microsoft.SemanticKernel.Connectors.EntityFramework连接器; - 不新增 EF 连接器,而是在需要时为单个数据库逐个新增连接器。
最终决策是方案 2。决策理由可归纳为四点:
- EF Provider 对集合管理操作的支持不统一,需要编写数据库特定代码来处理键与对象映射;
- 这些因素会使得 EF 连接器不可靠,且无法真正抽象底层数据库(没有抽象,只有转发);
- EF 支持、而 SK 尚无向量存储连接器的数据库数量极少(投入产出比极低);
- 逐一新增数据库连接器反而能精确贴合各数据库的特性。
决策的后续验证:仓库中的实际走向
该决策(2024-08 提出)在后续版本演进中得到了清晰的印证,可在当前仓库中直接查验:
1. 独立的数据库连接器按需落地,而非 EF 统一连接器。在 dotnet/src/VectorData 目录下,可以看到按数据库组织的独立目录:Chroma、Milvus、Pinecone、Qdrant、Redis、Weaviate、AzureAISearch、MongoDB、SqlServer、PgVector、SqliteVec、CosmosNoSql、CosmosMongoDB、InMemory 等。其中 MongoDB 与 SqlServer 等连接器的 README 明确说明其代码已迁移至各自的维护方仓库(如 MongoDB 官方维护的mongodb/mongo-mevd-provider、CommunityToolkit 的 AI 仓库),印证了"每个数据库由各自生态维护独立连接器"的演化方向。同时,dotnet/Directory.Packages.props 中可以看到Npgsql、CommunityToolkit.VectorData.PgVector、Testcontainers.MongoDB等按数据库引用的依赖,而非统一的 EF Core 依赖。
2. EF 并未被 Semantic Kernel 抛弃,而是回归它擅长的定位。仓库中存在 dotnet/src/Plugins/Plugins.StructuredData.EntityFramework,它并非向量存储连接器,而是基于Entity Framework 6.5的结构化数据访问插件(Microsoft.SemanticKernel.Plugins.StructuredData.EntityFramework),目标框架为net10.0;net8.0;net462。其项目文件中的注释"EntityFramework 6.5 is not compatible with .Net Standard 2.0"恰好印证了 ADR 中关于 EF 与 .NET Standard 兼容性的分析;对应的架构决策见 0068-structured-data-connector.md。也就是说:EF 被用于"让 AI 通过插件访问关系型结构化数据",而不是作为向量存储的统一抽象——这与 ADR 0051 的结论完全一致。
3. 集合管理的工程现实在代码中可见。ADR 0050 的最终设计(Option 6)采用了IVectorStore作为工厂返回IVectorStoreCollection<TKey, TRecord>的形态,集合创建与记录管理分离。向量数据连接器多数已外迁的事实,也从侧面说明:集合创建这类"数据库强相关"能力,天然应该由各数据库连接器自行实现,而不是由一个试图统一一切的 ORM 层承担。
启示:给连接器设计者的三条经验
回顾整份 ADR,可以提炼出对任何"统一连接器"方案都适用的判断准则:
- 抽象的价值取决于"差异是否被真正吸收"。EF 表面上统一了多数据库访问,但集合管理、键类型、向量类型映射这些核心差异并没有被吸收,只是被转移到了 EF 连接器内部,抽象因此名存实亡。
- "统一测试一套、到处运行"是伪命题。每个数据库实现的是 EF 功能子集的不同切片,SQLite 上的绿色测试无法背书 MongoDB 上的行为,测试矩阵随数据库数量线性甚至超线性扩张。
- 兼容性策略本身就是技术债的源头。当候选技术无法同时满足目标框架矩阵(.NET Standard 2.0)与长期演进(EF Core 而非 EF6)时,采纳它意味着要么收缩支持面,要么绑定到停止演进的分支——两者都不可接受。
对 Semantic Kernel 而言,这个决策最终换来了更可靠、更贴合各数据库特性的连接器体系:需要向量检索时,按数据库选用对应的专用连接器;需要结构化数据操作时,EF 作为插件出现在它最擅长的关系型数据场景中。
进一步阅读:完整的调研论证见 docs/decisions/0051-entity-framework-as-connector.md;向量存储设计背景见 docs/decisions/0050-updated-vector-store-design.md;EF 结构化数据插件的后续落地见 docs/decisions/0068-structured-data-connector.md 与 dotnet/src/Plugins/Plugins.StructuredData.EntityFramework;向量数据连接器清单见 dotnet/src/VectorData。
【免费下载链接】semantic-kernelIntegrate cutting-edge LLM technology quickly and easily into your apps项目地址: https://gitcode.com/GitHub_Trending/se/semantic-kernel
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考