استفاده از داده های مکانی در EfCore - قسمت دوم

استفاده از داده های مکانی در EfCore - قسمت دوم
فهرست مقاله [نمایش]

     در قسمت قبل با داده های مکانی آشنا شدیم، داده های مکانی بیانگر موقعیت فیزیکی و شکل اشیاء بر روی مختصات جغرافیایی هستند. بسیاری از بانک های اطلاعاتی از جمله SQL Server از داده های مکانی پشتیبانی می کنند و می توانیم در کنار سایر انواع داده ای، از داده های مکانی نیز در موجودیت های خودمان استفاده کنیم.
    به صورت پیشفرض داده های مکانی در EFCore  پشتیبانی نمی شوند مایکروسافت از نسخه EFCore 2.2 کتابخانه NetTopologySuite که به اختصار NTS هم گفته می شود را برای پشتیبانی از داده های مکانی ارائه کرد. پس برای استفاده از داده های مکانی در EFCore حتما باید از نسخه 2.2 به بالاتر استفاده کنیم و کتابخانه NetTopologySuite هم نصب کنیم.

     

    • نصب NetTopologySuite

    بسته کتابخانه NetTopologySuite را می توانیم از Nuget  نصب کنیم. این کتابخانه چهار نوع مختلف را ارائه کرده است که می توانیم بسته به Provider مورد نظرمان یکی از آنها را نصب کنیم.

     

    توضیحاتبسته NugetEf Core Provider
    پشتیبانی از MSSQL Server  در Entity Freamwork Core

    Microsoft.EntityFrameworkCore

    .SqlServer.NetTopologySuite

     

    Microsoft.EntityFrameworkCore.SqlServer
    پشتیبانی از پایگاه داده SQLite  در Entity Freamwork Core

    Microsoft.EntityFrameworkCore

    .Sqlite.NetTopologySuite

    Microsoft.EntityFrameworkCore.Sqlite
     NetTopologySuiteMicrosoft.EntityFrameworkCore.InMemory
    پشتیبانی از Npgsql در Entity Freamwork PostgreSQL

    Npgsql.EntityFrameworkCore.

    PostgreSQL.NetTopologySuite

    Npgsql.EntityFrameworkCore.PostgreSQL

      

     

     

    انواع داده مکانی در NetTopologySuite  

    شش نوع داده مکانی در کتابخانه NetTopologySuite  پشتیبانی می شود که می توانیم از آنها در موجودیت های برنامه استفاده کنیم. انواع داده ای NetTopologySuite در فضای نام NetTopologySuite.Geometries قرار دارند.

    • Point
    • LineString
    • Polygon
    • MultiPoint
    • MultiLineString
    • MultiPolygon

     

    توجه: در قسمت اول مقاله توضیح کاملی در مورد انواع داده های مکانی ارائه شده است.

    فعال کردن NetTopologySuite در DBContext

    همانطور که گفتیم NetTopologySuite یک کتابخانه مکانی برای فریمورک دات نت است که کار Mapping داده های مکانی در EntityFreamCore را انجام می دهد.
    برای فعال کردن mapping انوع داده ای NetTopologySuite به داده های مکانی باید در DBContxt  متُد UseNetTopologySuite را در قسمت provider مربوطه استفاده کنیم. به عنوان مثال در SqlServer به صورت زیر آن را فعال می کنیم.

    string connection = "Data Source=.;Initial Catalog=BugetoSpatialData;Integrated Security=True;MultipleActiveResultSets=true ";
    services.AddEntityFrameworkSqlServer()
    .AddDbContext<DataBaseContext>(option =>
    option.UseSqlServer(connection, x => x.UseNetTopologySuite()));

     

     استفاده از NetTopologySuite در موجودیت ها

    یک کلاس به نام Store ایجاد کرده ایم، از این کلاس برای نگهداری اطلاعات فروشگاه استفاده می کنیم. در اطلاعات فروشگاه ما قصد داریم که موقعیت مکانی فروشگاه هم در کنار دیگر اطلاعات آن نگهداری کنیم. برای نگهداری موقعیت مکانی یک فیلد با نام Location و از نوع Point به کلاس Store اضافه کرده ایم.
    برای نمایش یک موقعیت مکانی به دو عدد X,Y و یا همان Lat,Long نیاز داریم، نوع داده ای Point هم دو عدد X,Y را دریافت می کند. که X برای نگهداری Long و Y برای نگهداری Lat است. به همین دلیل برای نگهداری موقعیت مکانی فروشگاه از نوع داده ای Point استفاده کردیم. البته اگر هر فروشگاه چندین شعبه داشته باشد باید از نوع داده ای MultiPoint استفاده کنیم.

     

      using NetTopologySuite.Geometries;
      public class Store
        {
            public long Id { get; set; }
            public string Name { get; set; }
            public string Address { get; set; }
            public string PhoneNumber { get; set; }
            [Column(TypeName = "geometry")]
            public Point  Location { get; set; }
        }

       افزودن مقادیر

    برای ذخیره مکان یک شئ در بانک اطلاعاتی باید یک نمونه از نوع geometry با استفاده از طول عرض جغرافیایی آن شئ ایجاد کنیم و سپس این نمونه ساخته شده از نوع geometry را ذخیره نماییم. برای ایجاد نمونهgeometry می توانیم از متُد CreateGeometryFactory مربوط به کتابخانه NetTopologySuite استفاده کنیم. پس از ساخت یک نمونه از CreateGeometryFactory می توانیم با استفاده از تابع CreatePoint یک نقطه را ایجاد کنیم. این تابع طول عرض جغرافیایی را به عنوان پارامتر دریافت می کند.
    متُد CreateGeometryFactory پارامتری به نام SRID دریافت می کند. SRID شناسه منحصر به فردی است که در سیستم های مختصات جغرافیایی استفاده می شود و عدد 4326 یک استاندارد متداول است که بسیاری از برنامه ها از جمله، Waze ، Google Map  از آن  برای SRID استفاده کرده اند.


    1.    برای ایجاد یک Point از کد زیر استفاده می کنیم:

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

     

    2.    برای ایجاد یک LineString از کد زیر استفاده می کنیم:

     

              var geometryFactory = NtsGeometryServices.Instance.CreateGeometryFactory(srid:   4326);
                Coordinate[] LineStringArray = new Coordinate[3];
                LineStringArray[0] = new Coordinate(51.242079734802246, 35.63340706937167);
                LineStringArray[1] = new Coordinate(51.23916149139404, 35.63082591309715);
                LineStringArray[2] = new Coordinate(51.23504161834717, 35.633720988098574);
                var LineString = geometryFactory.CreateLineString(LineStringArray);

     


    3.    برای ایجاد Poygon از کد زیر استفاده می کنیم:

     

    var geometryFactory = NtsGeometryServices.Instance.CreateGeometryFactory(srid:   4326);
    
    Coordinate[] polygonArray = new Coordinate[5];
                polygonArray[0] = new Coordinate(51.394686698913574, 35.718608138232895);
                polygonArray[1] = new Coordinate(51.392154693603516, 35.71808549588366);
               polygonArray[2] = new Coordinate(51.39271259307861, 35.715507076789464);
                polygonArray[3] = new Coordinate(51.395244598388665, 35.71655239188316);
               polygonArray[4] = new Coordinate(51.394686698913574, 35.718608138232895);
    var polygone = geometryFactory.CreatePolygon(polygonArray);

     

    کد زیر افزودن یک فروشگاه به همراه موقعیت مکانی آن به مدل Store را انجام می دهد.

                 var geometryFactory = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326);
                var currentLocation = geometryFactory.CreatePoint(new NetTopologySuite.Geometries.Coordinate(51.258741, 36.254155));
    
                Store newStore = new Store()
                {
                    Name = "فروشگاه شماره یک",
                    Address = "تهران - میدان تیموری - خیابان قاسمی - پلاک 7",
                    PhoneNumber="09128698172",
                    Location = currentLocation,
                };
                _context.Stores.Add(newStore);
                _context.SaveChanges();

     

    کوئری گرفتن از داده های مکانی

    پس از نصب NetTopologySuite دستورات LINQ این کتابخانه برای استفاده دردسترس ما قرار دارند. این دستورات استفاده از داده های مکانی را برای ما بسیار راحت کرده و بسیاری از کوئری های پیچیده را می توانیم با این دستورات به سادگی اجرا کنیم.
    برای مثال اگر ما بخواهیم نزدیکترین فروشگاه به یک موقعیت مکانی را بدست بیاریم از متُد Distance استفاده می کنیم.

      var neareStore = db.Stores .OrderBy(c => c.Location.Distance(currentLocation))FirstOrDefault();

     

    داده های مکانی در SQLServer

    اگراز پایگاه داده SQLServer استفاده می کنید باید به این مورد توجه داشته باشید. به صورت پیش فرض در SQLServer نوع داده ای، داده های مکانی geography در نظر گرفته می شود.
    برای تغییر نوع داده ای به  geometry باید یکی از روش های زیر را اعمال کنید.


    1.    روش استفاده از Data Annotation

            [Column(TypeName = "geometry")]
            public Point  Location { get; set; }


    2.    روش استفاده از Fluent API
          

               protected override void OnModelCreating(ModelBuilder modelBuilder)
            {
    
                modelBuilder.Entity<Store>(p =>
                {
                    p.Property(store => store.Location).HasColumnType("geometry");
    
                    {
    
                    }
                });
            }

       

    امکانات NetTopologySuite

    در جدول زیر متُدها و خصوصیات کتابخانه NetTopologySuite را مشاهده می کنیم و مشخص می کنیم که در کدام Provider های مربوط به EFCore پشتیبانی می شود.

     

    NpgsqlSQLiteSQL Server (geography)SQL Server (geometry)متد
    Geometry.Area
    Geometry.AsBinary
    Geometry.AsText
     Geometry.Boundary

    Geometry.Buffer(double)
      Geometry.Buffer(double, int)
     Geometry.Centroid

    Geometry.Contains(Geometry)
    Geometry.ConvexHull()
      Geometry.CoveredBy(Geometry)
       Geometry.Covers(Geometry)
     Geometry.Crosses(Geometry)
    Geometry.Difference(Geometry)
    Geometry.Dimension
    Geometry.Disjoint(Geometry)
    Geometry.Distance(Geometry)
     Geometry.Envelope
       Geometry.EqualsExact(Geometry)
    Geometry.EqualsTopologically(Geometry)
    Geometry.GeometryType
     Geometry.GetGeometryN(int)
     Geometry.InteriorPoint
    Geometry.Intersection(Geometry)
    Geometry.Intersects(Geometry)
    Geometry.IsEmpty
     Geometry.IsSimple
     Geometry.IsValid
    Geometry.IsWithinDistance(Geometry, double)
     Geometry.Length
    Geometry.NumGeometries
    Geometry.NumPoints
    Geometry.OgcGeometryType
    Geometry.Overlaps(Geometry)
     Geometry.PointOnSurface
     Geometry.Relate(Geometry, string)
      Geometry.Reverse()
    Geometry.SRID
    Geometry.SymmetricDifference(Geometry)
    Geometry.ToBinary()
    Geometry.ToText()
     Geometry.Touches(Geometry)
      Geometry.Union()
    Geometry.Union(Geometry)
    Geometry.Within(Geometry)
    GeometryCollection.Count
    GeometryCollection[int]
    LineString.Count
    LineString.EndPoint
    LineString.GetPointN(int)
     LineString.IsClosed
    LineString.IsRing
    LineString.StartPoint
    MultiLineString.IsClosed
    Point.M
    Point.X
    Point.Y
    Point.Z
    Polygon.ExteriorRing
    Polygon.GetInteriorRingN(int)

     


    • نویسنده: احسان بابائی

    ارسال دیدگاه

    برای افزودن دیدگاه خود، نیاز است ابتدا وارد حساب کاربری‌تان شوید


    دیدگاه کاربران