C# 将几何图形转换为地理图形的实体框架

C# 将几何图形转换为地理图形的实体框架,c#,entity-framework,spatial,rdbms,ef-core-3.1,C#,Entity Framework,Spatial,Rdbms,Ef Core 3.1,我试图通过数据库中的实体类插入几何体对象,但始终返回错误“地理位置与几何体不兼容”。我最初收到一个字符串,该字符串传递几何坐标的X和Y值,并进行必要的转换以创建几何体提供的点类型,我不需要进行任何计算,因此几何体类型是我现在最适合使用的类型。我使用下面的函数进行转换: public static Geometry ConvertToGeometry(string coordinatesAux) { if(coordinatesAux == null) throw new

我试图通过数据库中的实体类插入几何体对象,但始终返回错误“地理位置与几何体不兼容”。我最初收到一个字符串,该字符串传递几何坐标的X和Y值,并进行必要的转换以创建几何体提供的点类型,我不需要进行任何计算,因此几何体类型是我现在最适合使用的类型。我使用下面的函数进行转换:

public static Geometry ConvertToGeometry(string coordinatesAux)
{
    if(coordinatesAux == null)
        throw new NullReferenceException();

    NumberFormatInfo formatProvider = new NumberFormatInfo();
    formatProvider.NumberGroupSeparator = ".";
        
    var geometryFactory = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326);
    var currentLocation = geometryFactory.CreatePoint(new Coordinate(
                                                           Convert.ToDouble(coordinatesAux.Substring(0, coordinatesAux.IndexOf(",")), formatProvider), 
                                                           Convert.ToDouble(coordinatesAux.Substring(coordinatesAux.IndexOf(",") + 1), formatProvider)));
        
    return currentLocation;                                                            
}
我还在Startup.cs中对db进行了必要的修改,以使用NetTopologySuite,但是当我尝试通过API插入值时,它返回最初描述的错误。我不知道问题是否出在我将字符串转换为几何体的过程中,或者是实体本身将字段识别为地理点

我尝试传递的值为-20.338113,-40.287893,我使用的实体类为:

public class Address : EntityBase<int>
{
    public Address(string district, string street, int number, string complement, string zipCode, 
    string cityDescription, string stateDescription, Geometry coordinates, int countryId, byte stateId, int cityId)
    {
        District = district;
        Street = street;
        Number = number;
        Complement = complement;
        ZipCode = zipCode;
        CityDescription = cityDescription;
        StateDescription = stateDescription;
        Coordinates = coordinates;
        CountryId = countryId;
        StateId = stateId;
        CityId = cityId;
    }

    public string District { get; set; }
    public string Street { get; set; }
    public int Number { get; set; }
    public string Complement { get; set; }
    public string ZipCode { get; set; }
    public string CityDescription { get; set; }
    public string StateDescription { get; set; }
    public virtual Geometry Coordinates { get; set; }
    public int CountryId { get; set; }
    public byte StateId { get; set; }
    public int CityId { get; set; }
    public int? CustomerId { get; set; }
    public int? StoreId { get; set; }
    public int? ProfessionalId { get; set; }
}

这里有一个很好的示例,可以映射到
几何体
地理
。你得看看你在做什么。(顺便说一句,您可能需要
地理
,因为SQL Server中的
几何
是一个平坦的欧几里德空间,无法为您提供精确的距离计算或纬度和经度坐标直线)

使用系统;
使用System.Collections.Generic;
使用System.ComponentModel.DataAnnotations;
使用System.ComponentModel.DataAnnotations.Schema;
使用System.Data.Common;
使用System.Linq;
使用System.Security.Cryptography;
使用Microsoft.EntityFrameworkCore;
使用Microsoft.Extensions.Logging;
使用NetTopologySuite.几何学;
命名空间EfCore3Test
{
公共类地址:EntityBase
{
公共广播(){}
公共广播(字符串区、字符串街、整数、字符串补码、字符串zipCode、,
字符串城市描述、字符串状态描述、几何坐标、int countryId、字节stateId、int cityId)
{
地区=地区;
街道=街道;
数字=数字;
补语=补语;
ZipCode=ZipCode;
城市描述=城市描述;
StateDescription=StateDescription;
坐标=坐标;
CountryId=CountryId;
StateId=StateId;
CityId=CityId;
}
公共字符串区域{get;set;}
公共字符串Street{get;set;}
公共整数{get;set;}
公共字符串补码{get;set;}
公共字符串ZipCode{get;set;}
公共字符串CityDescription{get;set;}
公共字符串StateDescription{get;set;}
//[列(TypeName=“geometry”)]
公共虚拟几何体坐标{get;set;}
public int CountryId{get;set;}
公共字节StateId{get;set;}
public int CityId{get;set;}
public int?CustomerId{get;set;}
public int?StoreId{get;set;}
public int?professional id{get;set;}
}
公共类实体库
{
公共T Id{get;set;}
}
公共类Db:DbContext
{
public Db():base()
{
}
私有静态只读ILoggerFactory loggerFactory=loggerFactory.Create(builder=>
{
builder.AddFilter((类别、级别)=>
category==DbLoggerCategory.Database.Command.Name
&&level==LogLevel.Information).AddConsole();
});
配置时受保护的覆盖无效(DBContextOptions Builder Options Builder)
{
var constr=“Server=localhost;database=efcore3test;integratedsecurity=true”;
选项Builder.UseLoggerFactory(loggerFactory)
.UseSqlServer(constr,o=>o.UserRelationalNulls().UseNetTopologySuite());
基本配置(选项生成器);
}
公共数据库集地址{get;set;}
模型创建时受保护的覆盖无效(ModelBuilder ModelBuilder)
{
基于模型创建(modelBuilder);
}
}
班级计划
{
静态void Main(字符串[]参数)
{
使用(var db=new db())
{
db.Database.EnsureDeleted();
db.Database.recreated();
var geometryFactory=NetTopologySuite.NtsGeometryServices.Instance.CreateGeometryFactory(srid:4326);
var currentLocation=geometryFactory.CreatePoint(新的NetTopologySuite.Geometries.Coordination(-122.121512,47.6739882));
var addr=新地址(“a”、“a”、“1”、“a”、“00223”、“城市”、“州”、当前位置,1、2、3);
数据库地址添加(地址);
db.SaveChanges();
}
}
}
}

请标记目标RDBMS,并在您的问题中包含DDL表。@DavidBrowne Microsoft制作的
CREATE TABLE Address(
    Id INT PRIMARY KEY IDENTITY(1, 1),
    District VARCHAR(50) NOT NULL, -- Bairro
    Street VARCHAR(100) NOT NULL, -- Rua
    --Description VARCHAR(100) NOT NULL,
    Number INT,
    Complement VARCHAR(100),
    ZipCode VARCHAR(20) NOT NULL,
    CityDescription VARCHAR(100),
    StateDescription VARCHAR(100),
    Coordinates GEOMETRY,
    
    CountryId INT FOREIGN KEY REFERENCES Country(Id) NOT NULL,
    StateId TINYINT FOREIGN KEY REFERENCES State(Id),
    CityId INT FOREIGN KEY REFERENCES City(Id),
    CustomerId INT FOREIGN KEY REFERENCES Customer(Id),
    StoreId INT FOREIGN KEY REFERENCES Store(Id),
    ProfessionalId INT FOREIGN KEY REFERENCES Professional(Id),

    INDEX IndexAddressCountryId NONCLUSTERED (CountryId),
    INDEX IndexAddressStateId NONCLUSTERED (StateId),
    INDEX IndexAddressCityId NONCLUSTERED (CityId),
    INDEX IndexAddressCustomerId NONCLUSTERED (CustomerId),
    INDEX IndexAddressStoreId NONCLUSTERED (StoreId),
    INDEX IndexAddressProfessionalId NONCLUSTERED (ProfessionalId)
)
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Common;
using System.Linq;
using System.Security.Cryptography;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using NetTopologySuite.Geometries;


namespace EfCore3Test
{

    public class Address : EntityBase<int>
    {
        public Address() { }
        public Address(string district, string street, int number, string complement, string zipCode,
        string cityDescription, string stateDescription, Geometry coordinates, int countryId, byte stateId, int cityId)
        {
            District = district;
            Street = street;
            Number = number;
            Complement = complement;
            ZipCode = zipCode;
            CityDescription = cityDescription;
            StateDescription = stateDescription;
            Coordinates = coordinates;
            CountryId = countryId;
            StateId = stateId;
            CityId = cityId;
        }

        public string District { get; set; }
        public string Street { get; set; }
        public int Number { get; set; }
        public string Complement { get; set; }
        public string ZipCode { get; set; }
        public string CityDescription { get; set; }
        public string StateDescription { get; set; }

        //[Column(TypeName ="geometry")]
        public virtual Geometry Coordinates { get; set; }
        public int CountryId { get; set; }
        public byte StateId { get; set; }
        public int CityId { get; set; }
        public int? CustomerId { get; set; }
        public int? StoreId { get; set; }
        public int? ProfessionalId { get; set; }
    }

    public class EntityBase<T>
    {
        public T Id { get; set; }
    }

    public class Db : DbContext
    {
           
        public Db(): base()
        {

        }

        private static readonly ILoggerFactory loggerFactory = LoggerFactory.Create(builder =>
        {
            builder.AddFilter((category, level) =>
               category == DbLoggerCategory.Database.Command.Name
               && level == LogLevel.Information).AddConsole();
        });
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            var constr = "Server = localhost; database = efcore3test; integrated security = true";
            optionsBuilder.UseLoggerFactory(loggerFactory)
                          .UseSqlServer(constr, o => o.UseRelationalNulls().UseNetTopologySuite());


            base.OnConfiguring(optionsBuilder);
        }

        public DbSet<Address> Addresses { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
        }

    }




    class Program
    {


    static void Main(string[] args)
        {
 

            using (var db = new Db())
            {

                db.Database.EnsureDeleted();
                db.Database.EnsureCreated();

                var geometryFactory = NetTopologySuite.NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326);
                var currentLocation = geometryFactory.CreatePoint(new NetTopologySuite.Geometries.Coordinate(-122.121512, 47.6739882));

                var addr = new Address("a", "a", 1, "a", "00223", "city", "state", currentLocation, 1, 2, 3);

                db.Addresses.Add(addr);

                db.SaveChanges();

            }

        }
    }

}