2009-09-29 23 views
22

Tôi đang cố gắng sử dụng Nhibernate với loại Sql 2008 Geography và đang gặp khó khăn. Tôi đang sử dụng Fluiber Nhibernate để cấu hình mà tôi khá mới để có thể là vấn đề là tốt.NHibernate.Spatial và Sql 2008 Loại địa lý - Cách cấu hình

Thứ nhất, lớp tôi đang cố gắng để tồn tại trông giống như sau:

public class LocationLog : FluentNHibernate.Data.Entity 
{ 
    public virtual new int Id {get;set;} 
    public virtual DateTime TimeStamp {get;set;} 
    public virtual GisSharpBlog.NetTopologySuite.Geometries.Point Location {get;set;} 
} 

Lớp bản đồ trông giống như:

public class LocationLogMap : ClassMap<LocationLog> 
{ 
    ImportType<GisSharpBlog.NetTopologySuite.Geometries.Point>(); 
    Id(x => x.Id); 
    Map(x => x.TimeStamp).Generated.Insert(); 
    Map(x => x.Location); 
} 

Để sử dụng MsSql2008GeographyDialect với thành thạo NHibernate, tôi đã tạo lớp cấu hình của riêng tôi:

public class Sql2008Configuration 
    : PersistenceConfiguration<Sql2008Configuration, MsSqlConnectionStringBuilder> 
{ 
    public Sql2008Configuration() 
    { 
     Driver<SqlClientDriver>(); 
    } 

    public static Sql2008Configuration MsSql2008 
    { 
     get { return new Sql2008Configuration().Dialect<MsSql2008GeographyDialect>(); } 
    } 
} 

vì vậy tôi có mã cấu hình như:

var configuration = Fluently.Configure() 
    .Database(Sql2008Configuration.MsSql2008.ConnectionString(c => c.Is(connectionString))) 
    .Mappings(m => m.FluentMappings 
    .AddFromAssemblyOf<LocationLog>() 
); 

Tất cả điều này để thiết lập một thực tế rằng tôi nhận được lỗi sau khi cố gắng kiên trì loại LocationLog cơ sở dữ liệu:

Một .NET Framework lỗi xảy ra trong quá trình thực hiện user- định nghĩa thường quy hoặc tổng hợp "địa lý": Hệ thống.ArgumentException: 24204: mã định danh tham chiếu không gian (SRID) là không hợp lệ. SRID được chỉ định phải khớp với một trong các SRID được hỗ trợ được hiển thị trong danh sách sys.spatial_reference_systems . System.ArgumentException: tại Microsoft.SqlServer.Types.SqlGeography.set_Srid (Int32 giá trị) tại Microsoft.SqlServer.Types.SqlGeography.Read (BinaryReader r) tại SqlGeography :: DeserializeValidate (IntPtr , Int32, CClrLobContext. *)

tôi đã đọc bài viết sau đây về cách cấu hình và sử dụng các thư viện Nhibernate không gian:

nhưng dường như không hữu ích. Bất kỳ ai có kinh nghiệm cấu hình Nhibernate để sử dụng các kiểu Địa lý không gian có thể cung cấp bất kỳ thông tin chi tiết nào sẽ được đánh giá cao.

Trả lời

10

Tôi đang ở trên cùng một chiếc thuyền và nhờ vào sự khởi đầu của bạn, tôi đã làm việc đó (chèn và đọc dữ liệu không gian). Đối với bất kỳ ai quan tâm, trước tiên lớp GisSharpBlog.NetTopologySuite.Geometries.Point nằm trong NetTopologySuite.dll, là một phần của tải về nHibernate.Spatial.

Thứ hai, theo James điểm, chắc chắn rằng bạn thiết lập các SRID đến 4326.

Và cuối cùng, bản đồ cần nhìn như thế này:

Map(a => a.Location).CustomType(typeof(NHibernate.Spatial.Type.GeometryType)); 

Tôi đang sử dụng Địa lý, nhưng tôi đọc một nơi nào đó mà sử dụng GeometryType có thể làm việc và nó cho tôi (tôi chèn một số điểm và xác minh nó trong cơ sở dữ liệu). Tôi cũng đọc rằng tốt nhất của nó để viết SQL Query cho Địa lý để bạn có thể sử dụng các phương pháp SQL 2008 không gian đặc biệt (trái ngược với việc sử dụng các tiêu chí).

1

Không thực sự là một câu trả lời nhưng câu hỏi ;-)

  • Bạn đang thiết lập một SRID trên GisSharpBlog.NetTopologySuite.Geometries.Point đối tượng?

Giá trị mặc định (vì điểm là hình) là 0 và sẽ cho bạn lỗi SQL khi cố gắng duy trì thuộc tính LocationLog.Location dưới dạng địa lý. 0 không phải là SRID hợp lệ cho các trường địa lý sql. Bạn sẽ cần phải xác định một từ khung nhìn sys.spatial_reference_systems.

  • Bạn đã thử không có Fluent NHibernate chưa?

Để loại bỏ nhiều thành phần khỏi sự cố.

2

Steve là đúng, bạn cần đặt rõ ràng SRID cho loại hình của mình. Nhìn vào nguồn NHibernate.Spatial (mà bạn có thể kiểm sử dụng SVN hoặc bất kỳ), làm một tìm kiếm cho SRID đi lên với điều này chôn cất tại các mã như một gợi ý bình luận:

<class name="MyGeoTableA"> 
    <property name="MyGeoColumn"> 
     <type name="NHibernate.Spatial.Type.GeometryType, NHibernate.Spatial"> 
      <param name="srid">1234</param> 
     </type> 
    </property> 
</class> 

Có vẻ như bạn cần phải thiết lập tham số có tên SRID cho bất kỳ số nào bạn cần (tra cứu trong bảng SRID). Rõ ràng đây là cấu hình XML trường học cũ nhưng thông thạo sẽ có một phương thức để thêm các tham số chuỗi khóa/giá trị. Hãy thử một lần.


Sửa

Sau khi nghiên cứu hơn một chút, tôi thấy rằng cố gắng thiết lập một thuộc tính SRID trên một cột không xác lập bản đồ XML NHibernate, nó ném một XmlSchemaValidationException. Thay vào đó, tôi thấy rằng các kiểu hình học trong NetNopologySuite có một thuộc tính SRID trên chính đối tượng đó và thiết lập điều này làm cho mọi thứ hoạt động. ví dụ.

LocationLog log = new LocationLog { Location = new Point() }; 
log.Location.SRID = 4326; 
Session.Save(log); 

Phải có cách tốt hơn để thực hiện việc này (định cấu hình thay vì đặt mọi lúc) nhưng tôi chưa làm việc đó. Nếu bạn nhìn vào bên trong lớp MsSql2008GeometryType, nó có một phương thức bảo vệ được gọi là SetDefaultSRID (IGeometry) - nó phải ở đó vì một lý do!

1

Bạn có thể tạo nhà máy của riêng mình bằng SRID mặc định. Ví dụ, bạn có thể tạo một mặt tiền cho các nhà máy như thế này:

public static class Default 
{ 
    private const int DefaultSrid = 4326; 

    public static readonly IGeometryFactory Factory; 

    static Default() 
    { 
     Factory = new GeometryFactory(new PrecisionModel(), DefaultSrid); 
    } 
} 

và sử dụng nó như thế này:

var point = Default.Factory.CreatePoint(new Coordinate(10, 10)); 

thay vì sử dụng từ khóa "mới". Bạn cũng có thể sử dụng phương thức Factory.Factory như một phương thức factory trong khung công tác IoC để tạo ra các hình học mới mà không có mặt tiền mặc định.

1

Tôi biết điều này hầu như không hữu ích nhưng trong mọi trường hợp. Sau khi thực hiện tất cả các lain đã nói làm sử dụng trong các truy vấn HQL của bạn SetParameter tham số thứ ba IType. Ý nghĩa trong

Hero hero = openSession.Get<Hero>(3);  
openSession.CreateQuery(
       "from Hero h where NHSP.Distance(h.Location,:thislocation)<1000" 
       ).SetParameter("thislocation", hero.Location, new CustomType(typeof(MsSql2008GeographyType), null)).SetResultTransformer(new DistinctRootEntityResultTransformer()) 
       .List(); 

CustomType mới (typeof (MsSql2008GeographyType), null) phải được thông qua hoặc bạn nhận được tất cả các quá famililar "System.ArgumentException: 24.204" của bạn.

Chỉ cần dành toàn bộ đêm để tìm hiểu điều đó.

Các vấn đề liên quan