EF框架操作postgresql,实现WKT类型坐标的插入,查询,以及判断是否相交

       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语句中必须要写一个相同别名对应实体名。

   新人发文,还请各位大佬指正。

  

原文地址:https://www.cnblogs.com/amigod/p/postgres.html