使用EF6.4.4和.NET6存储DbGeography类型数据时遇类型映射错误
问题描述
使用Entity Framework 6.4.4和.NET 6向数据库存储DbGeography类型数据时,调用SaveChanges()方法触发错误:No mapping exists from object type Microsoft.SqlServer.Types.SqlGeography to a known managed provider native type
当前使用的Microsoft.SqlServer.Types版本为160.1000.6,完整堆栈跟踪如下:
System.Data.Entity.Infrastructure.DbUpdateException: An error occurred while updating the entries. See the inner exception for details.
---> System.Data.Entity.Core.UpdateException: An error occurred while updating the entries. See the inner exception for details.
---> System.Data.Entity.Core.EntityCommandCompilationException: An error occurred while preparing the command definition. See the inner exception for details.
---> System.ArgumentException: No mapping exists from object type Microsoft.SqlServer.Types.SqlGeography to a known managed provider native type.
at System.Data.SqlClient.MetaType.GetMetaTypeFromValue(Type dataType, Object value, Boolean inferLen, Boolean streamAllowed)
at System.Data.SqlClient.MetaType.GetMetaTypeFromType(Type dataType)
at System.Data.SqlClient.SqlParameter.GetMetaTypeOnly()
at System.Data.SqlClient.SqlParameter.get_SqlDbType()
解决方法
1. 降级Microsoft.SqlServer.Types版本
EF6.4.4与最新版Microsoft.SqlServer.Types兼容性较差,建议降级至14.0.314.76或更早的稳定版本,该版本与EF6的类型映射逻辑匹配度更高。
2. 手动注册SqlGeography类型映射
在EF上下文的OnModelCreating方法中添加类型映射规则,确保EF能正确识别地理类型:
protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Properties<DbGeography>() .Configure(config => config.HasColumnType("geography")); }
同时在应用启动时注册SqlServer类型处理程序:
SqlProviderServices.SqlServerTypesAssemblyName = "Microsoft.SqlServer.Types, Version=14.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91";
3. 统一使用EF自带的DbGeography类型
确保代码中使用System.Data.Entity.Spatial.DbGeography而非直接引用Microsoft.SqlServer.Types.SqlGeography。若需从SqlGeography转换,可使用以下代码:
var dbGeography = DbGeography.FromText(sqlGeography.AsText(), sqlGeography.SRID);
4. 适配SqlClient版本
.NET6默认使用Microsoft.Data.SqlClient,但EF6.4.4对其支持有限,可切换回System.Data.SqlClient(推荐版本4.8.5),保证与EF6底层逻辑适配。
内容的提问来源于stack exchange,提问作者Tom van Oost

