1.組件配置
首先,要下載.NET for Postgresql的驅動,npgsql,EF6,以及EntityFramework6.Npgsql,版本號 3.1.1.0.
由於是mvc項目,所以,把相應的配置文件寫在web.config里面,如下:
1 <configSections> 2 <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --> 3 <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /> 4 </configSections>
由於項目數據的存儲是用的MongoDB,此代碼段必須添加在<configuration>標簽下的第一個子節點,是對EF框架的引入聲明.
<!--EF框架與Npgsql整合--> <entityFramework> <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework"> <parameters> <parameter value="v13.0" /> </parameters> </defaultConnectionFactory> <providers> <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" /> <provider invariantName="Npgsql" type="Npgsql.NpgsqlServices, EntityFramework6.Npgsql" /> </providers> </entityFramework>
此段配置是EF框架與npgsql的整合。
<system.data> <!--注冊npgSql組件--> <DbProviderFactories> <remove invariant="Npgsql" /> <add name="Npgsql" invariant="Npgsql" description=".Net Framework Data Provider for Postgresql" type="Npgsql.NpgsqlFactory, Npgsql" /> <add name="dotConnect for PostgreSQL" invariant="Devart.Data.PostgreSql" description="Devart dotConnect for PostgreSQL" type="Devart.Data.PostgreSql.PgSqlProviderFactory, Devart.Data.PostgreSql, Version= 7.7.804.0, Culture=neutral, PublicKeyToken=09af7300eec23701"/> </DbProviderFactories> </system.data>
此段配置,是對npgsql組件的注冊,缺失的話會報npgsql未注冊的異常。
用nuget直接下載上述組件,這些都應該會自動生成配置文件,我之前是因為寫了一個控制台程序進行嘗試,mvc項目里的組件
都是直接引用的控制台程序里面的。
<!--Postgresql數據庫的字符串連接信息--> <connectionStrings> <add name ="db" connectionString ="Server=localhost;Port=5432;Database=db;User Id=postgres;Password=123456;" providerName="Npgsql"/> </connectionStrings>
連接信息需要自己添加,不會生成。
2. 數據庫連接
這里遇到了一個問題,明明配置文件中密碼寫的沒問題,讀到后台代碼中時,ConnectString里總是沒有密碼,於是乎用笨方法,在c#代碼里面自己在重寫一遍ConnectString
public class dbFactory : DbContext 2 { 3 public dbFactory(string databaseName, bool isDoInitialize = false) 4 : base(databaseName) 5 { 6 if (!isDoInitialize) 7 { 8 Database.Connection.Open(); 9 Database.Connection.ConnectionString = "Server=127.0.0.1;Port=5432;Database=db;User Id=postgres;Password=123456"; 10 11 Database.SetInitializer<dbFactory>(null); 12 13 14 15 } 16 } 17 18 19 20 21 22 //public DbSet<Destination> Destination { set; get; } 23 public DbSet<PuKouMap> PuKouMap 24 { 25 set; 26 get; 27 28 } 29 public DbSet<Judyment> Judyment { set; get; } 30 }
而且必須要自己手動打開連接,否則初始化后連接狀態一直是Closed,不知道有什么更好的方法。
1 [Table("PuKouMapDb", Schema = "public")] 2 public class PuKouMap 3 { 4 [Key] 5 public int Id { set; get; } 6 public int Type { set; get; } 7 public string ObjectId { set; get; } 8 public string Polygon { set; get; } 9 public string ZipName { set; get; } 10 public string FilePath { set; get; } 11 public string FileNames { set; get; } 12 public string ObjectName { set; get; } 13 }
要在實體類上面加一個注解,實體類對應表名寫上,因為在sqlsever默認的架構師dbo,postgresql卻是public,所以在這要改一下。
1 public class BaseDao 2 { 3 public static dbFactory db = null; 4 /// <summary> 5 /// 派生類實例化時加載基類構造函數,進行數據庫連接 6 /// </summary> 7 static BaseDao() 8 { 9 db = new dbFactory("db"); 10 11 } 12 #region 得到建立連接后的數據操作接口 13 public dbFactory getDb() { 14 15 16 return db; 17 } 18 #endregion 19 }
1 public class QueryString 2 { 3 4 public static string Insert(PuKouMap p) { 5 String InsertAction = "INSERT INTO public.'PuKouMapDb' VALUES("+p.Type+","+p.ObjectId+","+"st_GeomFromText(" +"'"+ p.Polygon +"'"+",4326)"+","+p.ZipName+","+p.FilePath+","+p.FileNames+","+p.ObjectName+";)"; 6 return InsertAction; 7 } 8 #region 斷句加空格 9 public static string GetPoKouMapByObjectIdString(String ObjectId) { 10 11 String CheckAction = "SELECT a.\"Id\",a.\"Type\",a.\"ObjectId\",ST_ASTEXT(a.\"Polygon\") AS \"Polygon\",a.\"ZipName\",a.\"FilePath\",a.\"FileNames\",a.\"ObjectName\" " 12 +"from public.\"PuKouMapDb\" as a "+ 13 "where " 14 +"a.\"ObjectId\"='"+ObjectId+"'"; 15 16 return CheckAction; 17 } 18 #endregion 19 public static string IsIntersects(String PolygonNew,String Geometry) { 20 21 string IsIntersectsAction = "SELECT ST_Intersects(st_GeomFromText(" + "'" + PolygonNew + "')" + "," +"'"+ Geometry +"'" +") AS \"TrueOrFalse\""; 22 return IsIntersectsAction; 23 } 24 25 26 27 }
postgresql的sql語句必須要注意的地方就是表名和字段名必須要加雙引號,所以用了轉義字符,插入直接用EF框架提供的Add(),方法就行了,會以坐標系缺省的情況插入進去.查詢要用到ST_ASTEXT函數進行geometry類型向文本類型的轉換,語句用EF框架的sqlQuery執行(感覺還不如用原生方法,做geomoetry分析,都必須用到postgis的空間分析函數,必須要寫sql)
判斷是否相交則用ST_Intersects函數對兩個geometry類型進行判斷,返回值是一個bool類型,由於EF框架沒有找到銜接postgresql的操作,返回值貌似只有對象,所以自己寫了一個bool值實體類。
public class Judyment { [Key] public bool TrueOrFalse { set; get; } }
相當於是一個存放結果的容器。應當注意sql語句中必須要寫一個相同別名對應實體名。
新人發文,還請各位大佬指正。
