Entity Framework Core: Type Udt is not supported on this platform. (Spatial Data - Geography)

前端 未结 3 571
醉酒成梦
醉酒成梦 2020-12-06 08:25

I\'m experimenting with entity framework core and stumbled upon an error I\'ve never seen before and can\'t figure out how to fix it. I\'m using .net Core Web API 2.0 with E

3条回答
  •  长情又很酷
    2020-12-06 09:03

    UPDATE: Since EF Core 2.2 there is support for spatial data!:

    http://portainer/#/stacks/kolibry-acc_8ssg5qantkr2dgrbxsamsikf6

    -------------------------

    Eli, tnx for you're solution. For me it was almost the perfect solution. I had 2 problems:

    Problems

    1. An other application also inserts directly into the database (temporary solution, this will be changed in the future).
    2. When getting the first 50 entities the data must be ordered by distance, so the 50 nearest entities will be returned.

    Solutions

    1. Instead of updating the location table from code I use a trigger on my visit table. This trigger will fill or insert, delete or update the Location table. So the create, update, delete function don't have to do anything else than saving the entity.
    
        create trigger VisitLocation_trigger on Visit
        after UPDATE, INSERT, DELETE
        as
    
        if exists(SELECT * from inserted)
            If exists(Select * from deleted)
                BEGIN
                    -- UPDATE
                    UPDATE visit_location SET location = GEOGRAPHY::Point(Latitude, Longitude, 4326) FROM visit_location JOIN inserted ON visit_location.visitid = inserted.id
                END
            else
                BEGIN
                    -- INSERT
                    INSERT INTO visit_location SELECT Id, GEOGRAPHY::Point(Latitude, Longitude, 4326) FROM inserted
                END
        else
            BEGIN
                -- DELETE
                declare @visitId int;
                SELECT @visitId = Id from deleted i;
                DELETE visit_location WHERE visit_location.visitid = @visitId 
            end
    
    1. The query for getting the first 50 must be a raw sql query, that will look like this:
    
    
        _context.Visit.FromSql(
            "SELECT TOP 50 v.* " +
            "FROM visit v " +
            "INNER JOIN visit_location vl ON v.id = vl.visitid " +
            "WHERE v.date > {0} " +
            "AND GEOGRAPHY::Point({1},{2}, 4326).STDistance(Location) < {3} " +
            "ORDER BY GEOGRAPHY::Point({1},{2}, 4326).STDistance(Location)",
            startDate, latitude, longitude, radius).ToList();
    
    

    CRUD

    Read

    
    
        public async Task GetByIdAsync(int id)
        {
            return await _context.Visit.AsNoTracking().SingleOrDefaultAsync(x => x.Id == id);
        }
    
    
    
    
         public IList GetLastVisitsForHouseIdsByCoordinates(DateTime startDate, double longitude, double latitude, long radius)
            {
                return
    
                    _context.Visit.FromSql("SELECT TOP 50 v.* " +
                                           "FROM visit v " +
                                           "INNER JOIN visit_location vl ON v.id = vl.visitid " +
                                           "WHERE v.IsLastVisit = 1 " +
                                           "AND v.date > {0} " +
                                           "AND GEOGRAPHY::Point({1},{2}, 4326).STDistance(Location) < {3} " +
                                           "ORDER BY GEOGRAPHY::Point({1},{2}, 4326).STDistance(Location)",
                        startDate, latitude, longitude, radius).ToList();
            }
        

    Create

    
    
        public async Task CreateAsync(Visit visit)
        {
            _context.Visit.Add(visit);
            await _context.SaveChangesAsync();
            return visit;  
        }
    
    

    Update

    
    
        public async Task UpdateAsync(Visit visit)
        {
            _context.Visit.Attach(visit);
            _context.Entry(visit).State = EntityState.Modified;
            await _context.SaveChangesAsync();
            return visit;
        }
    
    

    Delete

    
    
        public async Task DeleteAsync(Visit visit)
        {
            _dbContext.Remove(entityToUpdate);
            _context.Entry(visit).State = EntityState.Deleted;
            await _context.SaveChangesAsync();
            return visit;
        }
    
    

    The database models

    
        public class Visit
        {
            public int Id { get; set; }
    
            [Required]
            public VisitStatus Status { get; set; }
    
            [Required]
            public double? Latitude { get; set; }
    
            [Required]
            public double? Longitude { get; set; }
    
            public Location Location { get; set; }
    
            [Required]
            public DateTime Date { get; set; }
    
            public string Street { get; set; }
    
            public int? StreetNumber { get; set; }
    
            public string StreetNumberLetter { get; set; }
    
            public string StreetNumberLetterAddition { get; set; }
    
            public string City { get; set; }
        }
    
        public struct Location
        {
            public double Longitude { get; set; }
            public double Latitude { get; set; }
        }
    

提交回复
热议问题