ASP NET, NET Framework, MONO, SQL, Visual Studio | Professional Programs | Программист Еремин В.В.
(ASP.NET) ASP NET (2010 год)

Этюды на ASP.NET. Пример сайта на СУБД PostgreSQL

В этом топике я покажу step-by-step как создать простейший сайт на PostgreSQL и опубликую общую рыбку сайта со всем необходимым окружением. Эта страничка является продолжением более общей странички: Используем PostgreSQL вместо MS SQL в проектах на .NET и ASP.NET. Эта страничка также является примером технологии MONO - Low cost and platform independent ASP.NET - be free with MONO, позволяющей работать ASP.NET-сайтам на Linux.

При работе с PostgreSQL в ASP.NET есть пару ньансов, в частности я стремлюсь по возможность сохранять коннект в пределах сессии (чего нет смысла делать при работе с MS SQL или MySQL). Для этого я открываю коннект при старте сессии. Global.asax у меня содержит вот такие строки:


   1:  <%@ Application Language="VB" %>
   2:   
   3:  <script runat="server">
   4:   
   5:  .....
   6:   
   7:      Sub Session_Start(ByVal sender As Object, ByVal e As EventArgs)
   8:          Dim PG1 As New PG1.SQL_Postgres
   9:          Session("PG1") = PG1
  10:      End Sub
  11:   
  12:      Sub Session_End(ByVal sender As Object, ByVal e As EventArgs)
  13:          If Session("PG1") IsNot Nothing Then
  14:              CType(Session("PG1"), PG1.SQL_Postgres).Close()
  15:          End If
  16:      End Sub
  17:         
  18:  </script>

Надо конечно, добавить к сайту пару ссылок на библиотеки Npgsql.dll и Mono.Security.dll, которые при стандартной инсталяции NPGSQL находятся в Win по подобному адресу C:\Program Files\Npgsql2.0.8-bin-ms.net3.5sp1\Npgsql2.0.8-bin-ms.net3.5sp1\bin. Кроме того, я вообще ложу в GAC Npgsql.dll - тогда ссылку на провайдер доступа с PostgreSQL можно вообще не ставить на сайте.

Конфиг сайта на ASP.NET 3.5 после добавления ссылки на Npgsql и строки коннекта к базе будет выглядеть вот так (укажите свой пароль):


   1:  ....
   2:      <connectionStrings>
   3:          <add name="SQLServer_ConnectionStrings" connectionString="HOST=127.0.0.1;PORT=5432;PROTOCOL=3;DATABASE=Disk;USER ID=postgres;POOLING=True;CONNECTIONLIFETIME=1000;MINPOOLSIZE=100;MAXPOOLSIZE=1024;COMMANDTIMEOUT=20;INTEGRATED SECURITY=False;"
   4:          providerName="Npgsql"/>
   5:      </connectionStrings>
   6:   
   7:      <system.web>
   8:          <compilation debug="true" strict="false" explicit="true">
   9:              <assemblies>
  10:                  <add assembly="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
  11:                  <add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
  12:                  <add assembly="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
  13:                  <add assembly="System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
  14:                  <add assembly="Npgsql, Version=2.0.8.0, Culture=neutral, PublicKeyToken=5D8B90D52F46FDA7"/>
  15:              </assemblies>
  16:          </compilation>
  17:  .....

Для удобства c PostgreSQL я сделал крошечную обвязочку, закрывающую ридер (если я забыл его закрыть в основном коде) и считывающую строку коннекта из конфига (чтобы не вспоминать имени строки коннекта). Кроме того она восстанавливает коннект при потере связи с СУБД и также в эту обвязку я позже собирался дописать обработку ошибок коннекта. Я откомпилировал этот крошечный класс, уложил его в библиотечку PG1 и просто ставлю ссылки на этот класс на своих сайтах.

И вот собственно код странички. Я покажу хандлер, а страничка будет выглядеть ровно так же:


   1:  <%@ WebHandler Language="VB" Class="RemoteSQL" %>
   2:   
   3:  Imports System
   4:  Imports System.Web
   5:   
   6:  Public Class RemoteSQL : Implements IHttpHandler, IRequiresSessionState
   7:      
   8:      
   9:      Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
  10:          context.Response.ContentType = "text/plain"
  11:          PG_Safe_Connection(context)
  12:          Dim RDR1 As Npgsql.NpgsqlDataReader = PG1.PG.ExecRDR("Select * from ""МаркаАвто""")
  13:          While RDR1.Read
  14:              context.Response.Write(RDR1(3) & vbCrLf)
  15:          End While
  16:          RDR1.Close()
  17:      End Sub
  18:   
  19:      
  20:      Dim PG1 As PG1.SQL_Postgres
  21:      Sub PG_Safe_Connection(ByVal context As HttpContext)
  22:          If context.Current.Session("PG1") IsNot Nothing Then
  23:              PG1 = context.Current.Session("PG1")
  24:          Else
  25:              PG1 = New PG1.SQL_Postgres
  26:              context.Current.Session("PG1") = PG1
  27:          End If
  28:          PG1.CheckConnect()
  29:      End Sub
  30:      
  31:      Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
  32:          Get
  33:              Return False
  34:          End Get
  35:      End Property
  36:   
  37:  End Class

Как видите, хандлер показывает то же, что и PgAdmin:




Для полноценной ASPX-странички можно даже вот этот хвостик (строки 20-29) утопить в базовую страничку. Проще всего это сделать поместив в app_code базовый класс всех страничек сайта (который несомненно в вашем проекте позднее разростется и будет не только коннект к базе поддерживать, но и аутентификацию юзеров проверять и многое другое):


   1:  Imports Microsoft.VisualBasic
   2:   
   3:  Public Class BasePage
   4:      Inherits System.Web.UI.Page
   5:   
   6:      Public Sub New()
   7:          MyBase.New()
   8:      End Sub
   9:   
  10:      Public PG1 As PG1.SQL_Postgres
  11:      Public Sub PG_Safe_Connection()
  12:          If HttpContext.Current.Session("PG1") IsNot Nothing Then
  13:              PG1 = HttpContext.Current.Session("PG1")
  14:          Else
  15:              PG1 = New PG1.SQL_Postgres
  16:              HttpContext.Current.Session("PG1") = PG1
  17:          End If
  18:          PG1.CheckConnect()
  19:      End Sub
  20:  End Class

Теперь вот такая простейшая страничка для генерации открытых/закрытых RSA-ключей будет выглядеть совсем просто:




   1:  <%@ Page Language="VB" MasterPageFile="~/M1.master" AutoEventWireup="false" CodeFile="RSA1.aspx.vb"  Inherits="RSA" %>
   2:   
   3:  <%@ Register Assembly="AspCommon2009" Namespace="vbnet2009" TagPrefix="cc1" %>
   4:  <asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server">
   5:      <div style="text-align: left">
   6:          <cc1:Navigator ID="Navigator1" runat="server" />
   7:          <h4>Создать новые RSA-ключи для ассимметричного шифрования?</h4>
   8:          <asp:Button ID="Button1" runat="server" Text="Yes" Width="50px" />
   9:          <asp:Button ID="Button2" runat="server" Text="No" Width="50px" />
  10:          <br />
  11:          <asp:Label ID="lErr1" runat="server" ForeColor="Red" Text=""></asp:Label>
  12:      </div>
  13:  </asp:Content>

   1:  Partial Class RSA
   2:      Inherits BasePage
   3:   
   4:      Protected Sub RSA_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
   5:          PG_Safe_Connection()
   6:      End Sub
   7:   
   8:      Protected Sub Button2_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button2.Click
   9:          Response.Redirect("Default.aspx")
  10:      End Sub
  11:   
  12:      Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
  13:          Try
  14:              Dim RSA As New System.Security.Cryptography.RSACryptoServiceProvider()
  15:              Dim PublicKey As String = RSA.ToXmlString(False)
  16:              Dim PrivateKey As String = RSA.ToXmlString(True)
  17:              PG1.PG.ExecScalar("INSERT INTO ""RSA_KEY"" (""PublicKey"",""PrivateKey"") VALUES ('" & PublicKey & "' , '" & PrivateKey & "');")
  18:              Response.Redirect("Default.aspx")
  19:          Catch ex As Exception
  20:              lErr1.Text = ex.Message
  21:          End Try
  22:      End Sub
  23:   
  24:  End Class

Как вы видите, эта форма всего-навсего создает новые асимметричные ключи и укладывает их в такую табличку:


   1:  CREATE TABLE "RSA_KEY"
   2:  (
   3:    i serial NOT NULL,
   4:    "PublicKey" character varying,
   5:    "PrivateKey" character varying,
   6:    CONSTRAINT "Rsa_primary_key" PRIMARY KEY (i)
   7:  )
   8:  WITH (
   9:    OIDS=FALSE
  10:  );
  11:  ALTER TABLE "RSA_KEY" OWNER TO postgres;

Достать из нее открытый RSA-ключ можно таким же хандлером буквально в две строчки:


   1:                  'вообще-то это лишь самый первый шаг длинного протокола
   2:                  Dim PublicKey As String = GetPublicKey()
   3:                  context.Response.ContentType = "text/Xml"
   4:                  context.Response.Write(PublicKey)


   1:      'Достать из базы сеекретный ключ RSA
   2:      Private Function GetPrivateKey(ByVal context As HttpContext) As String
   3:          Dim PrivateKey As String
   4:          Dim RDR1 As Npgsql.NpgsqlDataReader = PG1.PG.ExecRDR("select ""PrivateKey"" from ""RSA_KEY"" order by i desc limit 1")
   5:          If RDR1.Read Then
   6:              PrivateKey = RDR1("PrivateKey")
   7:          End If
   8:          RDR1.Close()
   9:          Return PrivateKey
  10:      End Function
  11:      
  12:      'Достать из базы публичный ключ RSA
  13:      Private Function GetPublicKey() As String
  14:          Dim PublicKey As String
  15:          Dim RDR1 As Npgsql.NpgsqlDataReader = PG1.PG.ExecRDR("select ""PublicKey"" from ""RSA_KEY"" order by i desc limit 1")
  16:          If RDR1.Read Then
  17:              PublicKey = RDR1("PublicKey")
  18:          End If
  19:          RDR1.Close()
  20:          Return PublicKey
  21:      End Function

Обратите внимание, что я в этот раз (как и всегда) публикую не просто какие-то помои - плоды теоретических измышлений, а небольшие, но ключевые фрагменты реального живого кода, используемые как для моих терминальных сетей на PostgreSQL, так и для работы моего хостинга http://asp-net.ru/. Опубликованный фрагмент находится по адресу http://activator.asp-net.ru/Activate.ashx. Этот фрагмент кода также используется во многих моих коммерческих продуктах с закрытым исходным кодом, например WebActivator - клиент/сервер защиты от копирования для платных программ.

http://mono-net.ru/


Комментарии к этой страничке ( )
ссылка на эту страничку: http://www.vb-net.ru/PostgreSQL_AspNet/index.htm
<На главную>  <В раздел ASP>  <В раздел NET>  <В раздел SQL>  <В раздел Разное>  <Написать автору>  < Поблагодарить>