SQL Server와 함께 MVC ASP.Net 공간 데이터 사용
Entity Framework 5에서 매우 기대되는 기능 중 하나는 공간 지원입니다.
SQL 2008이 출시된 이후 많은 개발자들이 Entity Framework에서 Spatial 데이터 형식을 지원해 줄 것을 요청해 왔습니다. Microsoft ORM 사용자에게는 공간 데이터를 사용하여 .NET 비즈니스 응용 프로그램을 빠르게 만드는 것이 꿈이었습니다. 올해 5월, EF5(Entity Framework 5)의 릴리스 후보가 발표되었습니다. 이 버전은 이전 EF 버전에 비해 성능이 향상되었으며 공간 형식도 지원합니다. EF5의 공간 기능을 사용하려면 .NET 4.5가 필요합니다.
EF5의 공간 기능을 사용하려면 .NET 4.5가 필요합니다. 즉, Visual Studios 2012가 설치되어 있어야 합니다. VS 2012의 릴리스 후보는 여기에서 다운로드 할 수 있습니다 http://www.microsoft.com/visualstudio/en-us
Entity Framework의 공간 데이터
.NET 4.5에서 Entity Framework 5.0 이전에는 저장 프로시저 또는 원시 SQL 명령을 사용하여 공간 데이터에 액세스해야 했습니다. 그러나 Entity Framework 5에서 Microsoft는 새로운 DbGeometry 및 DbGeography 형식을 도입했습니다. 이러한 불변의 위치 유형은 기하학 함수를 사용하여 공간 점을 조작할 수 있는 다양한 기능을 제공하며, 이는 위의 SQL 구문에서 설명한 것과 같은 일반적인 공간 쿼리를 수행하는 데 사용할 수 있습니다.
DbGeography/DbGeometry 형식은 변경할 수 없으므로 한 번 만든 후에는 쓸 수 없습니다. 그것들은 당신이 그것들을 인스턴스화하기 위해 팩토리 메소드를 사용해야한다는 점에서 약간 이상합니다 - 그들은 constructor ()를 가지고 있지 않으며 Latitude 및 Longitude와 같은 속성에 할당 할 수 없습니다.
이러한 형식은 System.Data.Spatial 네임스페이스의 System.Data.Entity 어셈블리에 정의되어 있다는 점을 언급하는 것이 중요합니다. 지금쯤이면 Microsoft.SqlServer.Types 네임스페이스에 정의된 SqlGeometry 및 SqlGeography 형식을 사용했을 것입니다
공간 데이터로 모델 만들기
먼저 샘플 데이터베이스 Northwind 및 SpatialDemo의 엔터티를 포함하는 간단한 Entity Framework 모델을 만들어 보겠습니다. world라는 엔터티에는 DbGeometry 형식의 geom 속성이 포함되어 있습니다. 샘플에서는 SQL Server 2012를 사용하지만 SQL Server 2008에서 실행할 수 있습니다.
[EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=true)]
[DataMemberAttribute()]
public global::System.Data.Spatial.DbGeometry geom
{
get
{
return _geom;
}
set
{
OngeomChanging(value);
ReportPropertyChanging("geom");
_geom = StructuralObject.SetValidValue(value, true, "geom");
ReportPropertyChanged("geom");
OngeomChanged();
}
}
private global::System.Data.Spatial.DbGeometry _geom;
partial void OngeomChanging(global::System.Data.Spatial.DbGeometry value);
partial void OngeomChanged();
Northwind 엔터티

공간 데이터를 포함한 샘플 SpatialDemo 데이터베이스. 테이블 월드는 "geom"이라는 지오메트리 유형에서 제출되었습니다. 이 필드에는 국가의 윤곽이 다각형으로 포함됩니다

SpatialDemo 데이터베이스에서 생성된 엔티티 세계에는 지오메트리 유형의 "geom" 필드가 포함되어 있습니다.

Entity Framework 5 RC 및 공간 데이터를 사용하는 ASP.Net MVC 4 응용 프로그램
이제 ASP.Net MVC 응용 프로그램에서 공간 데이터를 사용하는 것이 매우 쉽습니다.
- Controller
컨트롤러는 Infragistics jQuery 컨트롤이 있는 대시보드가 포함된 보기를 반환합니다.
#region DashboardJs
public ActionResult DashboardJs()
{
ViewBag.Message = "Spatial Data Dashboard";
return View();
}
#endregion //DashboardJs
- Spatial Data Maintenance
DbGeometry / DbGeography 유형의 데이터가있는 경우 직렬화 할 수 없습니다. 두 가지 옵션이 있습니다.
- 공간 데이터 형식을 WKT(Well Known Text)로 변환하고 JSON 또는 XML의 일부로 클라이언트(보기)에 보내려면
- serialize할 수 있는 고유한 클래스를 사용하려면
이 샘플에서는 두 번째 방법을 보여 줍니다
CountryByName 메소드는 결과를 뷰에서 사용할 수 있도록 JSON으로 직렬화합니다.
#region CountryByName
[OutputCache(VaryByParam = "countryName", Duration = 120)]
public JsonResult CountryByName(string countryName)
{
switch (countryName)
{
case "UK":
countryName = "United Kingdom";
break;
case "USA":
countryName = "United States";
break;
}
var results = spDemo.worlds.Where(x => x.CNTRY_NAME == countryName);
List ret = new List();
foreach (world country in results)
{
CountryInfo info = new CountryInfo
{
Id = country.ID,
Code = country.CODE,
CountryName = country.CNTRY_NAME,
Population = country.POP_CNTRY,
Extend = GetGeometryBoundary(country)
};
ret.Add(info);
}
var retVal = Json(ret, JsonRequestBehavior.AllowGet);
return retVal;
}
#endregion //CountryByName
GetGeometryBoundary는 DbGeometry 인스턴스의 봉투(Envelope)를 나타내는 점 목록을 가져오는 데 사용되는 도우미 메서드입니다. DbGeometry/DbGeography 포인트 인덱스는 1부터 시작한다는 것을 잊지 마세요!
#region GetGeometryBoundary
public static SpatialRect GetGeometryBoundary(world country)
{
List multiPoints = new List();
var numPoints = country.geom.Envelope.ElementAt(1).PointCount;
for (int i = 1; i <= numpoints="" i="" pre="">
{
SpatialPoint pnt = new SpatialPoint((double)(country.geom.Envelope.ElementAt(1).PointAt(i).XCoordinate), (double)(country.geom.Envelope.ElementAt(1).PointAt(i).YCoordinate));
multiPoints.Add(pnt);
}
SpatialRect rect = multiPoints.GetBounds();
return rect;
}
#endregion //GetGeometryBoundary
ContryInfo는 데이터를 직렬화하는 데 사용되는 도우미 클래스입니다
#region CountryInfo
public class CountryInfo
{
public int Id { get; set; }
public string Code { get; set; }
public string CountryName { get; set; }
public long? Population { get; set; }
public SpatialRect Extend { get; set; }
}
#endregion //CountryInfo
SpatialPoint는 포인트 데이터를 유지하는 도우미 클래스입니다. 다음을 사용할 수 있습니다.
#region SpatialPoint
public class SpatialPoint
{
public SpatialPoint(double x, double y)
{
this.X = x;
this.Y = y;
}
public double X { get; set; }
public double Y { get; set; }
}
#endregion //SpatialPoint
SpatialRect는 국가를 확장하기위한 도우미 클래스입니다.
#region SpatialRect
public struct SpatialRect
{
public SpatialRect(double pLeft, double pTop, double pWidth, double pHeight)
{
left = pLeft;
top = pTop;
width = pWidth;
height = pHeight;
}
public double left;
public double top;
public double width;
public double height;
}
#endregion //SpatialRect
GetBounds는 점 목록의 경계를 가져오는 데 사용되는 확장 메서드입니다.
#region Extensions
public static class Extensions
{
#region GetBounds
public static SpatialRect GetBounds(this IList points)
{
double xmin = Double.PositiveInfinity;
double ymin = Double.PositiveInfinity;
double xmax = Double.NegativeInfinity;
double ymax = Double.NegativeInfinity;
SpatialPoint p;
for (var i = 0; i < points.Count; i++)
{
p = points[i];
xmin = Math.Min(xmin, p.X);
ymin = Math.Min(ymin, p.Y);
xmax = Math.Max(xmax, p.X);
ymax = Math.Max(ymax, p.Y);
}
if (Double.IsInfinity(xmin) || Double.IsInfinity(ymin) || Double.IsInfinity(ymin) || Double.IsInfinity(ymax))
{
return new SpatialRect(0.0, 0.0, 0.0, 0.0);
}
return new SpatialRect(xmin, ymin, xmax - xmin, ymax - ymin);
}
#endregion //GetBounds
}
#endregion //Extensions
보기
이 뷰는 jQuery 그리드, 차트 및 맵 Infragistics 대시보드를 제공합니다.
샘플에서 가장 중요한 부분은 공간 데이터(이 경우 국가 확장)를 반환하는 컨트롤러의 메서드를 쿼리하는 방법입니다.
var countryUrl = "/Home/CountryByName?countryName=" + args.row.element[0].cells[1].textContent
...
$.getJSON(countryUrl,
function (json, text) {
$.each(json, function (index, value) {
var country = value;
var extend = country["Extend"];
var zoom = $("#map").igMap("getZoomFromGeographic", extend);
$("#map").igMap("option", "windowRect", zoom);
});
});
Infragistics jQuery Map instance definition.
$("#map").igMap({
width: "500px",
height: "500px",
panModifier: "control",
horizontalZoomable: true,
verticalZoomable: true,
windowResponse: "immediate",
overviewPlusDetailPaneVisibility: "visible",
seriesMouseLeftButtonUp: function (ui, args) {
var tets = args;
}
});
선택한 고객의 국가를 확대/축소하는 Infragistics jQuery Grid입니다.
$('#grid').igGrid({
virtualization: false, height: 280, width: 650,
dataSource: "/Home/Customers",
autoGenerateColumns: false,
columns: [
{ headerText: "Customer ID", key: "CustomerID", width: "120px", dataType: "string" },
{ headerText: "Country", key: "Country", width: "150px", dataType: "string" },
{ headerText: "City", key: "City", dataType: "string" },
{ headerText: "Contact Name", key: "ContactName", dataType: "string" },
{headerText: "Phone", key: "Phone", dataType: "string" }
],
features:
[{
name: 'Selection',
mode: 'row',
multipleSelection: false,
rowSelectionChanged: function (ui, args) {
$("#chart").igDataChart({
dataSource: "/Home/Orders?userID=" + args.row.element[0].cells[0].textContent
});
selected = args.row.element[0].cells[0].textContent; //keep track of selected user
var countryUrl = "/Home/CountryByName?countryName=" + args.row.element[0].cells[1].textContent
$.getJSON(countryUrl,
function (json, text) {
$.each(json, function (index, value) {
var country = value;
var extend = country["Extend"];
var zoom = $("#map").igMap("getZoomFromGeographic", extend);
$("#map").igMap("option", "windowRect", zoom);
});
});
}
}
,
{
name: 'Sorting',
type: "remote"
},
{
name: 'Paging',
type: "local",
pageSize: 10
}]
})
공간 데이터 활용 사례
응용 프로그램을 실행하고 메뉴에서 "Spatial Data Dashboard"를 선택합니다.


igGrid에서 고객을 선택하고 지도에 클라이언트가 속한 국가가 어떻게 표시되는지 확인합니다.


여기에서 샘플의 소스 코드를 다운로드할 수 있습니다.
이 샘플을 실행하려면 Northwind 및 SpatialDemo 샘플 데이터베이스를 다운로드할 수 있습니다
항상 그렇듯이 Twitter: @mihailmateev 및 @ Infragistics, 해시태그가 있는 모든 트윗 #infragistcs Facebook, Google+, LinkedIn 및 Infragistics Friends 사용자 그룹에서 연락을 유지할 수 있습니다!