Abiks järgnev päring
SELECT dm_exec_sessions.session_id, dm_exec_sessions.status
, dm_exec_sessions.login_name, dm_exec_sessions.original_login_name
, dm_exec_connections.net_transport
, dm_exec_connections.connect_time
, dm_exec_sessions.login_time
, dm_exec_connections.protocol_type
, dm_exec_connections.client_net_address
, dm_exec_connections.client_tcp_port
, dm_exec_connections.auth_scheme
, dm_exec_sessions.HOST_NAME, dm_exec_sessions.NT_DOMAIN
, dm_exec_sessions.program_name, dm_exec_sessions.client_interface_name
, dm_exec_sessions.language, dm_exec_sessions.client_version
, dm_exec_requests.command, dm_exec_requests.wait_type, dm_exec_requests.wait_time, dm_exec_requests.wait_resource
FROM sys.dm_exec_sessions
JOIN sys.dm_exec_connections ON (dm_exec_sessions.session_id = dm_exec_connections.session_id )
INNER JOIN master..sysprocesses ON (dm_exec_sessions.session_id = sysprocesses.SPID)
LEFT JOIN sys.dm_exec_requests ON (dm_exec_sessions.session_id = dm_exec_requests.session_id)
WHERE DB_NAME(sysprocesses.dbid) = DB_NAME()
--AND dm_exec_sessions.status != 'sleeping'
dm_exec_sessions.session_id põhjal võib teha KILL sellele ühendusele
dm_exec_sessions.program_name saad seada Web.Config faili ConnectionStringis Application Name parameetriga niimoodi
connectionString="Data Source=SQL2008SERVER;Min Pool Size=2;Application Name=MINURAKENDUS; ...
kolmapäev, 30. detsember 2009
reede, 18. detsember 2009
GridView TemplateField veeru päise muutmine nii, et sortimine jääks alles
TemplateFieldil võib päise ja sorteerimise kirjeldada nii
Kui vaja nüüd veeru päise teksti dünaamiliselt muuta nii, et sorteerimise võimalus alles jääks
siis tee eraldi HeaderTemplate, kuhu poeta Linkbutton, mille CommandName on "Sort" ja CommandArgument on see andmebaasi väli mille järgi sorteerida tahad
Kui nüüd vaja päise teksti muuta, saad teha nii kusjuures sortimine jääb alles
protected void GridViewKolijad_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.Header)
{
LinkButton ud = (LinkButton)e.Row.FindControl("LinkButtonVana");
if (ud != null)
{
ud.Text = this.RadioButtonListSisse.SelectedValue == "0" ? Resources.Resource.NewContract : Resources.Resource.PreviousContract;
}
}
}
Kui vaja nüüd veeru päise teksti dünaamiliselt muuta nii, et sorteerimise võimalus alles jääks
siis tee eraldi HeaderTemplate, kuhu poeta Linkbutton, mille CommandName on "Sort" ja CommandArgument on see andmebaasi väli mille järgi sorteerida tahad
Kui nüüd vaja päise teksti muuta, saad teha nii kusjuures sortimine jääb alles
protected void GridViewKolijad_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.Header)
{
LinkButton ud = (LinkButton)e.Row.FindControl("LinkButtonVana");
if (ud != null)
{
ud.Text = this.RadioButtonListSisse.SelectedValue == "0" ? Resources.Resource.NewContract : Resources.Resource.PreviousContract;
}
}
}
reede, 4. detsember 2009
II astme SQL süstimise tõkestamine reapiiranguga
Üks viis kuidas tõkestada SCRIPT, IFRAME, FORM, BODY ja muude murdskriptimisvõimaluste lisamist andmebaasi on panna string tüüpi väljade peale reapiirangud näiteks LIKE operandi kasutades
ALTER TABLE [dbo].[HD_PROBLEMS] WITH CHECK ADD CONSTRAINT [CK_HD_PROBLEMS_SQL_INJECTION] CHECK ((NOT [problemDescription] LIKE '%<_%')) Siin LIKE '%<_%' tähendab kõik stringid kus < järel on mingi character sümbol (ka tühik)
ALTER TABLE [dbo].[HD_PROBLEMS] WITH CHECK ADD CONSTRAINT [CK_HD_PROBLEMS_SQL_INJECTION] CHECK ((NOT [problemDescription] LIKE '%<[A-Z]%'))
Siin LIKE '%<[A-Z]%' kõik stringid kus < järel on mingi täht A kuni Z
ALTER TABLE [dbo].[HD_PROBLEMS] WITH CHECK ADD CONSTRAINT [CK_HD_PROBLEMS_SQL_INJECTION] CHECK ((NOT [problemDescription] LIKE '%<[ASIDBMFH/]%'))
Siin LIKE '%<[ASIDBMFH/]%' tähendab kõik stringid kus < järel on mingi sümbol nimekirjast ASIDBMFH/
Koos NOT-iga saame lausendi mis kontrollib "ei ole mustas nimekirjas".
Standardid soovitavad muidugi kasutada valge nimekirja kontrollimist.
Kuidas töötab
Kui nüüd üritatakse XSS-i kirjutada andmebaasi välja sisse (II astme rünnak)
siis reapiirang asub tegevusse ja andmeid muuta ei lubata
ALTER TABLE [dbo].[HD_PROBLEMS] WITH CHECK ADD CONSTRAINT [CK_HD_PROBLEMS_SQL_INJECTION] CHECK ((NOT [problemDescription] LIKE '%<_%')) Siin LIKE '%<_%' tähendab kõik stringid kus < järel on mingi character sümbol (ka tühik)
ALTER TABLE [dbo].[HD_PROBLEMS] WITH CHECK ADD CONSTRAINT [CK_HD_PROBLEMS_SQL_INJECTION] CHECK ((NOT [problemDescription] LIKE '%<[A-Z]%'))
Siin LIKE '%<[A-Z]%' kõik stringid kus < järel on mingi täht A kuni Z
ALTER TABLE [dbo].[HD_PROBLEMS] WITH CHECK ADD CONSTRAINT [CK_HD_PROBLEMS_SQL_INJECTION] CHECK ((NOT [problemDescription] LIKE '%<[ASIDBMFH/]%'))
Siin LIKE '%<[ASIDBMFH/]%' tähendab kõik stringid kus < järel on mingi sümbol nimekirjast ASIDBMFH/
Koos NOT-iga saame lausendi mis kontrollib "ei ole mustas nimekirjas".
Standardid soovitavad muidugi kasutada valge nimekirja kontrollimist.
Kuidas töötab
Kui nüüd üritatakse XSS-i kirjutada andmebaasi välja sisse (II astme rünnak)
siis reapiirang asub tegevusse ja andmeid muuta ei lubata
neljapäev, 26. november 2009
String tüüpi muutuja polsterdamine SQL süstimise vastu
Kui ei pääse üle ega ümber sellest, et vaja dünaamiline SQL kirjutada ja sp_executesql kasutada ei saa siis string tüüpi muutujad (VARCHAR, NVARCHAR, CHAR jne) polsterda järgmiselt:
REPLACE(@otsiparam,'''','''''') ning enne ja pärast seda veel kolmed ülakomad
näiteks niimoodi:
DECLARE @os NVARCHAR(MAX)
SET @otsiparam=LTRIM(RTRIM(ISNULL(@otsiparam,'')) --juhuks, kui tühikud ees ja taga võivad probleemiks olla ning parameeter võib ka NULL olla.
SET @os='SELECT TOP 1 NIMED.NIMI FROM DBO.NIMED WITH(NOLOCK) WHERE NIMED.ID = '''+REPLACE(@otsiparam,'''','''''')+''''
EXECUTE (@os)
Kui vaja ainult ühte rida andmebaasist kätte saada siis mõtekas TOP 1
SELECT lausesse lisada. Aitab OR 1=1 rünnakute vastu.
See muutuja, mida EXECUTE lausega käima tõmbad võiks olla NVARCHAR(MAX) tüüpi, siis ei jõuta seda ülakomasid ''''''' täis ajada, ennem astuvad võrgu piirangud vahele.
C# käib polsterdamine nii
public string Polsterda(string inputSQL)
{
return inputSQL.Replace("'", "''");
}
REPLACE(@otsiparam,'''','''''') ning enne ja pärast seda veel kolmed ülakomad
näiteks niimoodi:
DECLARE @os NVARCHAR(MAX)
SET @otsiparam=LTRIM(RTRIM(ISNULL(@otsiparam,'')) --juhuks, kui tühikud ees ja taga võivad probleemiks olla ning parameeter võib ka NULL olla.
SET @os='SELECT TOP 1 NIMED.NIMI FROM DBO.NIMED WITH(NOLOCK) WHERE NIMED.ID = '''+REPLACE(@otsiparam,'''','''''')+''''
EXECUTE (@os)
Kui vaja ainult ühte rida andmebaasist kätte saada siis mõtekas TOP 1
SELECT lausesse lisada. Aitab OR 1=1 rünnakute vastu.
See muutuja, mida EXECUTE lausega käima tõmbad võiks olla NVARCHAR(MAX) tüüpi, siis ei jõuta seda ülakomasid ''''''' täis ajada, ennem astuvad võrgu piirangud vahele.
C# käib polsterdamine nii
public string Polsterda(string inputSQL)
{
return inputSQL.Replace("'", "''");
}
kolmapäev, 18. november 2009
Võõra XmlNode panemine teise XmlDocument -i sisse
Kõik XmlNode tüüpi asjad on konkreetselt seotud selle XmlDocument-iga, mille külge nad tehti.
Kui nüüd tahta "võõrast" XmlNode panna teise XmlDocument-i sisse tuleb see importida
//algne XmlDocument
XmlDocument res = new XmlDocument();
XmlElement elem = res.CreateElement("SkoorResult");
res.AppendChild(elem);
// see "nd" on nüüd see "võõras" node, mille kuskilt mujalt saame
TimeZoneInfo localZone = TimeZoneInfo.Local;
TimeSpan vahe = localZone.GetUtcOffset(System.DateTime.Now);
XmlNode nd = MakeRequest(nod,vahe);
//impordime sisse
XmlNode nodeToMove = res.ImportNode(nd, true);
res.DocumentElement.AppendChild(nodeToMove);
Kui nüüd tahta "võõrast" XmlNode panna teise XmlDocument-i sisse tuleb see importida
//algne XmlDocument
XmlDocument res = new XmlDocument();
XmlElement elem = res.CreateElement("SkoorResult");
res.AppendChild(elem);
// see "nd" on nüüd see "võõras" node, mille kuskilt mujalt saame
TimeZoneInfo localZone = TimeZoneInfo.Local;
TimeSpan vahe = localZone.GetUtcOffset(System.DateTime.Now);
XmlNode nd = MakeRequest(nod,vahe);
//impordime sisse
XmlNode nodeToMove = res.ImportNode(nd, true);
res.DocumentElement.AppendChild(nodeToMove);
neljapäev, 5. november 2009
Veebilehe ViewState suuruse näitaja Firefoxile
Selline kaval asi on olemas:
https://addons.mozilla.org/en-US/firefox/addon/5956
Kui avad mingi ASPX lehe, rehkendab lehe allaäärde veebilehe ViewState suuruse.
ViewState on teatavasti see info, mida IIS lehele kaasa paneb, et seal veebilehe elementide "mälu" hoida. Mida suurem ViewState seda "paksem" leht, mida väiksem ViewState seda nobedamini leht kohale tiritakse.
Veebirakenduse puhul tegemist sisuliselt dilemmaga. Kas küsida iga kord andmed andmebaasist uuesti (koormab rohkem andmebaasiserverit) või kord juba küsitud andmed panna lehe ViewState(mis teeb lehe mahult suuremaks ja närib rohkem ribalaiust ära).
https://addons.mozilla.org/en-US/firefox/addon/5956
Kui avad mingi ASPX lehe, rehkendab lehe allaäärde veebilehe ViewState suuruse.
ViewState on teatavasti see info, mida IIS lehele kaasa paneb, et seal veebilehe elementide "mälu" hoida. Mida suurem ViewState seda "paksem" leht, mida väiksem ViewState seda nobedamini leht kohale tiritakse.
Veebirakenduse puhul tegemist sisuliselt dilemmaga. Kas küsida iga kord andmed andmebaasist uuesti (koormab rohkem andmebaasiserverit) või kord juba küsitud andmed panna lehe ViewState(mis teeb lehe mahult suuremaks ja närib rohkem ribalaiust ära).
kolmapäev, 28. oktoober 2009
Ära näita sirviku JavaScriptile küpsiseid
reede, 23. oktoober 2009
XML andmete näitamine TreeView ja XmlDataSourcega
Andmebaasis on XML väli kuhu paneb sisse igasugu andmeid, peamiselt logimisinfot mille jaoks iga kord tabelisse eraldi tulpa teha ei viitsi. XML andmete stuktuur kuidas kunagi
mõnel rohkem
mõnel vähem
ja tulevikus võib vajadusel juurde lisada.
Ekraanil hierarhiliste andmete näitamiseks sobib hästi TreeView nimeline control, XML andmed salvestab XmlDataSourceTähele peab panema, et XmlDataSource on EnableCaching vaikimisi True, kuna vaja andmebaasist dünaamiliselt iga kord uusi andmeid näidata tuleb
EnableCaching="false" seada
Vaikmisi TreeView seab andmed XML elementde külhge, et ekraanil näitab ainult
Options, AcceptedUser ja RELATED_CONTRACT teksti nii nagu XML andmete tippude nimed on, kuna see mis andmebaasi XML väljast tuleb võib igakord erinev olla siis
ontreenodedatabound="TreeViewExtraInfo_TreeNodeDataBound" eventis tuleb natuke käsitsitööd teha, näiteks nii:
protected void TreeViewExtraInfo_TreeNodeDataBound(object sender, TreeNodeEventArgs e)
{
try
{
System.Xml.XmlElement cdf = (System.Xml.XmlElement)e.Node.DataItem;
if (cdf.Name == "Options") //juurelement
{
e.Node.Text = Resources.Resource.ExtraInfo;
}
else
{
if (cdf.InnerXml != "")
{
try //kui ta sellist node nimetust ei leia resursi tekstidest, võtame NODE enda nime
{
e.Node.Text = HttpContext.GetGlobalResourceObject("Resource", cdf.Name).ToString()+ " " + cdf.InnerText;
}
catch (SystemException ex)
{
e.Node.Text = cdf.Name + " " + cdf.InnerText;
}
}
}
if (cdf.HasAttributes) //kui on atribuute siis lisame elemendile ühe alamtipu
{
for (int i = 0; i < cdf.Attributes.Count; i++)
{
TreeNode db;
try
{
//kas ressursi tekstides on tipu elemendi kirjeldus olemas
db = new TreeNode(HttpContext.GetGlobalResourceObject("Resource", cdf.Attributes[i].Name).ToString() + " " + cdf.Attributes[i].Value);
}
catch (SystemException ex)
{
db = new TreeNode(cdf.Attributes[i].Name + " " + cdf.Attributes[i].Value);
}
e.Node.ChildNodes.Add(db);
}
}
}
catch (SystemException ex)
{
this.CustomValidator1.ErrorMessage = ex.Message;
this.CustomValidator1.IsValid = false;
}
}
Ekraanile aga paistab:
AcceptedUseri all on atribuutidest tehtud lisatipud
Andmete külgepanemine käib XmlDataSourceExtraInfo.Data property kaudu
this.XmlDataSourceExtraInfo.Data = this.ApplicationOptions(this.application_id);
this.TreeViewExtraInfo.DataBind();
siin this.ApplicationOptions(this.application_id) tagastab XML stringi mille andmebaasi XML väljast loen
public string ApplicationOptions(int applicationId)
{
string retu = "";
using (SqlConnection konn = new SqlConnection(Configuration.ConnectionString))
{
SqlCommand komm = new SqlCommand("SELECT [dbo].[APPLICATION_OPTIONS_KUIDO_S](" + applicationId.ToString() + ")", konn);
komm.CommandType = CommandType.Text;
konn.Open();
Object ret = komm.ExecuteScalar();
if (!ret.Equals(DBNull.Value))
{
retu = ret.ToString();
}
konn.Close();
}
return retu;
}
mõnel rohkem
mõnel vähem
ja tulevikus võib vajadusel juurde lisada.
Ekraanil hierarhiliste andmete näitamiseks sobib hästi TreeView nimeline control, XML andmed salvestab XmlDataSourceTähele peab panema, et XmlDataSource on EnableCaching vaikimisi True, kuna vaja andmebaasist dünaamiliselt iga kord uusi andmeid näidata tuleb
EnableCaching="false" seada
Vaikmisi TreeView seab andmed XML elementde külhge, et ekraanil näitab ainult
Options, AcceptedUser ja RELATED_CONTRACT teksti nii nagu XML andmete tippude nimed on, kuna see mis andmebaasi XML väljast tuleb võib igakord erinev olla siis
ontreenodedatabound="TreeViewExtraInfo_TreeNodeDataBound" eventis tuleb natuke käsitsitööd teha, näiteks nii:
protected void TreeViewExtraInfo_TreeNodeDataBound(object sender, TreeNodeEventArgs e)
{
try
{
System.Xml.XmlElement cdf = (System.Xml.XmlElement)e.Node.DataItem;
if (cdf.Name == "Options") //juurelement
{
e.Node.Text = Resources.Resource.ExtraInfo;
}
else
{
if (cdf.InnerXml != "")
{
try //kui ta sellist node nimetust ei leia resursi tekstidest, võtame NODE enda nime
{
e.Node.Text = HttpContext.GetGlobalResourceObject("Resource", cdf.Name).ToString()+ " " + cdf.InnerText;
}
catch (SystemException ex)
{
e.Node.Text = cdf.Name + " " + cdf.InnerText;
}
}
}
if (cdf.HasAttributes) //kui on atribuute siis lisame elemendile ühe alamtipu
{
for (int i = 0; i < cdf.Attributes.Count; i++)
{
TreeNode db;
try
{
//kas ressursi tekstides on tipu elemendi kirjeldus olemas
db = new TreeNode(HttpContext.GetGlobalResourceObject("Resource", cdf.Attributes[i].Name).ToString() + " " + cdf.Attributes[i].Value);
}
catch (SystemException ex)
{
db = new TreeNode(cdf.Attributes[i].Name + " " + cdf.Attributes[i].Value);
}
e.Node.ChildNodes.Add(db);
}
}
}
catch (SystemException ex)
{
this.CustomValidator1.ErrorMessage = ex.Message;
this.CustomValidator1.IsValid = false;
}
}
Ekraanile aga paistab:
AcceptedUseri all on atribuutidest tehtud lisatipud
Andmete külgepanemine käib XmlDataSourceExtraInfo.Data property kaudu
this.XmlDataSourceExtraInfo.Data = this.ApplicationOptions(this.application_id);
this.TreeViewExtraInfo.DataBind();
siin this.ApplicationOptions(this.application_id) tagastab XML stringi mille andmebaasi XML väljast loen
public string ApplicationOptions(int applicationId)
{
string retu = "";
using (SqlConnection konn = new SqlConnection(Configuration.ConnectionString))
{
SqlCommand komm = new SqlCommand("SELECT [dbo].[APPLICATION_OPTIONS_KUIDO_S](" + applicationId.ToString() + ")", konn);
komm.CommandType = CommandType.Text;
konn.Open();
Object ret = komm.ExecuteScalar();
if (!ret.Equals(DBNull.Value))
{
retu = ret.ToString();
}
konn.Close();
}
return retu;
}
teisipäev, 20. oktoober 2009
GridView tulba peitmine andmebaasi välja põhjal
Kui vaja teha mingi PIVOT päring andmebaasist või üldse juhtudel kus andmebaasist võib iga kord erinevate tulpade arvuga Tabular Data Stream (TDS) vastu tulla ning vaja seda ekraanil kuvada nii, et mõnda tulpa ei näitaks siis üks asja lahendus on GridView kasutamine AutoGenerateColumns="True" seadistusega.
Kuna GridView sisse saab teha igasugu tüüpi tulpasid siis põhimõte on see, et kontrollime, kas on teatud tüüpi tulp. Näiteks kontrollime, kas on BoundField tüüpi tulp ja kui on siis kas DataField langeb otsitavaga kokku.
///
/// tagastab GridView asp:BoundField tüüpi tulba indeksi DataField nime põhjal
///
///
/// fieldName on DataFieldi väli mida otsida
///
public int GetGridColumnIndex(GridView grd, string fieldName)
{
for (int i = 0; i < grd.Columns.Count; i++)
{
DataControlField field = grd.Columns[i];
//üritame pöörata BoundField-iks
BoundField bfield = field as BoundField;
//kui on BoundField ja DataField langeb ka kokku tagastame tulba indeksi
if (bfield != null && bfield.DataField.ToUpper() == fieldName.ToUpper())
{
return i;
}
}
return -1;
}
Tulba peitmine, PEIDATULP on see TDS tulp mida näidata ei taha
//leiame selle tulba numbri, mida ei tohi näidata
int tlnr = GetGridColumnIndex(this.GridViewKeeled, "PEIDATULP");
if (tlnr != -1)
{
this.GridViewKeeled.Columns[tlnr].Visible = false;
}
Kuna GridView sisse saab teha igasugu tüüpi tulpasid siis põhimõte on see, et kontrollime, kas on teatud tüüpi tulp. Näiteks kontrollime, kas on BoundField tüüpi tulp ja kui on siis kas DataField langeb otsitavaga kokku.
///
/// tagastab GridView asp:BoundField tüüpi tulba indeksi DataField nime põhjal
///
///
/// fieldName on DataFieldi väli mida otsida
///
public int GetGridColumnIndex(GridView grd, string fieldName)
{
for (int i = 0; i < grd.Columns.Count; i++)
{
DataControlField field = grd.Columns[i];
//üritame pöörata BoundField-iks
BoundField bfield = field as BoundField;
//kui on BoundField ja DataField langeb ka kokku tagastame tulba indeksi
if (bfield != null && bfield.DataField.ToUpper() == fieldName.ToUpper())
{
return i;
}
}
return -1;
}
Tulba peitmine, PEIDATULP on see TDS tulp mida näidata ei taha
//leiame selle tulba numbri, mida ei tohi näidata
int tlnr = GetGridColumnIndex(this.GridViewKeeled, "PEIDATULP");
if (tlnr != -1)
{
this.GridViewKeeled.Columns[tlnr].Visible = false;
}
kolmapäev, 14. oktoober 2009
BULK INSERT tekstifailist CLR-i kasutades
Sai kogemata SQLSERVER 2008 Web Edition maha müüdud ja siis avastatud, et Integration Services selle versiooni sees ei olegi. Kokkuvõttes tuleb asjad ise teha ja loeme nüüd BULK INSERT käsuga otse tekstifailist:
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
public partial class StoredProcedures
{
[Microsoft.SqlServer.Server.SqlProcedure]
public static void HansaImport(SqlString fail, SqlString kataloog, SqlString sihttabel, SqlInt32 kustutafail)
{
//teeme sisendparameetrite kontrolli ja lõikame lõpud maha
string siht = Convert.ToString(sihttabel);
siht=siht.Substring(0, (siht.Length > 30 ? 30 : siht.Length));
string kat = Convert.ToString(kataloog);
kat = kat.Substring(0, (kat.Length > 30 ? 30 : kat.Length));
string fai = Convert.ToString(fail);
fai = fai.Substring(0, (fai.Length > 20 ? 20 : fai.Length));
string impafail = kat + fai;
if (System.IO.File.Exists(impafail))
{
using (SqlConnection konn = new SqlConnection("Context connection=true"))
{
SqlCommand komm = new SqlCommand("TRUNCATE TABLE " + siht + "; BULK INSERT " + siht + " FROM '" + impafail + "' WITH (FIELDTERMINATOR ='\t',ROWTERMINATOR ='\n', BATCHSIZE = 10000)", konn);
konn.Open();
komm.ExecuteNonQuery();
konn.Close();
if (kustutafail == 1)
{
System.IO.File.Delete(impafail);
}
}
}
else
{
throw new SystemException("CLR Error !! Missing file: " + fai + " in directory: " + kat);
}
}
}
Kui nüüd värk käivitada Management Studio alt siis kõik OK aga kui panna jooksma kui andmebaasi töö tuleb selline viga
Bulk load data conversion error (type mismatch or invalid character for the specified codepage) for row
Tekstifailis on kuupäev kujul 23.10.2009
Et asi andmebaasi tööna jooksma saada anname temale kuupäeva formaadi ette
SET DATEFORMAT DMY
EXECUTE [dbo].[HansaImport]
@fail='arved.txt'
,@kataloog='D:\HANSA_IMPORT\'
,@sihttabel='[dbo].[HANSA_ARVED_TEMP]'
,@kustutafail=0
SQL SERVER Agent kasutab SQL SERVERi enda kuupäeva seadeid asjadest aru saamiseks
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
public partial class StoredProcedures
{
[Microsoft.SqlServer.Server.SqlProcedure]
public static void HansaImport(SqlString fail, SqlString kataloog, SqlString sihttabel, SqlInt32 kustutafail)
{
//teeme sisendparameetrite kontrolli ja lõikame lõpud maha
string siht = Convert.ToString(sihttabel);
siht=siht.Substring(0, (siht.Length > 30 ? 30 : siht.Length));
string kat = Convert.ToString(kataloog);
kat = kat.Substring(0, (kat.Length > 30 ? 30 : kat.Length));
string fai = Convert.ToString(fail);
fai = fai.Substring(0, (fai.Length > 20 ? 20 : fai.Length));
string impafail = kat + fai;
if (System.IO.File.Exists(impafail))
{
using (SqlConnection konn = new SqlConnection("Context connection=true"))
{
SqlCommand komm = new SqlCommand("TRUNCATE TABLE " + siht + "; BULK INSERT " + siht + " FROM '" + impafail + "' WITH (FIELDTERMINATOR ='\t',ROWTERMINATOR ='\n', BATCHSIZE = 10000)", konn);
konn.Open();
komm.ExecuteNonQuery();
konn.Close();
if (kustutafail == 1)
{
System.IO.File.Delete(impafail);
}
}
}
else
{
throw new SystemException("CLR Error !! Missing file: " + fai + " in directory: " + kat);
}
}
}
Kui nüüd värk käivitada Management Studio alt siis kõik OK aga kui panna jooksma kui andmebaasi töö tuleb selline viga
Bulk load data conversion error (type mismatch or invalid character for the specified codepage) for row
Tekstifailis on kuupäev kujul 23.10.2009
Et asi andmebaasi tööna jooksma saada anname temale kuupäeva formaadi ette
SET DATEFORMAT DMY
EXECUTE [dbo].[HansaImport]
@fail='arved.txt'
,@kataloog='D:\HANSA_IMPORT\'
,@sihttabel='[dbo].[HANSA_ARVED_TEMP]'
,@kustutafail=0
SQL SERVER Agent kasutab SQL SERVERi enda kuupäeva seadeid asjadest aru saamiseks
reede, 9. oktoober 2009
Andmebaasi tööde ülevaade
Selleks, et mingi SQL SERVER Agent-i töö käiks peab
1. Töö ise olema lubatud
2. Töö enda plaanur olema lubatud
Kuna mõnikord unustad selle märkeruudu "Enabled" peale sättida siis abiks SP mis teeb ülevaate SQL Agenti andmebaasi töödest.
ENABLED väli näitab kas töö on peatatud
SCHEDULE_ENABLED väli näitab kas töö plaanur on peatatud
[dbo].[SQLSERVERAGENTDATETIME_KUIDO] funktsiooni ma olen kirjeldanud
varasemalt siin http://kuidoveeb.blogspot.com/2009/04/sql-server-agent-kuupaeva-funktsioon.html
Parameeter @job_names võimaldab filtreerida töö nime alguse järgi
-- =============================================
-- Description: Andmebaasi tööde nimekiri
-- =============================================
CREATE PROCEDURE [dbo].[WINTIME_JOBS_KUIDO_S]
@job_names NVARCHAR(128)=N'MINUTOOD'
WITH EXECUTE AS 'DBO' --käivitame teatud kasutaja õigustes kuna pole mõtet and igaühele otse tabelitele juurdepääsu
AS
BEGIN
SET NOCOUNT ON
DECLARE @err INT
IF RIGHT(@job_names,1) <> '%'
SET @job_names=@job_names+'%'
--OTSIME KÕIGEPEALT SOBIVAD TÖÖD VÄLJA (filter nime alguse järgi)
DECLARE @tood TABLE (job_id UNIQUEIDENTIFIER PRIMARY KEY, job_name NVARCHAR(128) COLLATE DATABASE_DEFAULT, enabled TINYINT,
job_owner NVARCHAR(128) COLLATE DATABASE_DEFAULT NULL )
INSERT INTO @tood (job_id, job_name, [enabled] , job_owner)
SELECT sj.JOB_ID, sj.NAME, sj.[enabled],su.name FROM [msdb]..sysjobs sj
LEFT JOIN msdb..[SYSUSERS] su ON (sj.owner_sid = su.sid )
WHERE sj.name LIKE @job_names
--TEEME ÜLEVAATE
SELECT ISNULL(b.job_owner,'') AS job_owner, b.job_name, b.job_id, b.[enabled]
,[dbo].[SQLSERVERAGENTDATETIME_KUIDO](c.next_run_date,c.next_run_time) AS NEXT_RUN_TIME
,a.step_name, a.subsystem, a.command, a.database_name
,a.step_id, a.step_name, c.schedule_enabled
,Hist.[MESSAGE] AS LAST_RUN_MESSAGE, Hist.LAST_RUN_TIME
,Hist.[RUN_DURATION] AS LAST_RUN_DURATION, Hist.RUN_STATUS AS LAST_RUN_STATUS
FROM msdb..sysjobsteps a
INNER JOIN @tood b ON ( a.job_id =b.job_id )
INNER JOIN (SELECT sc.job_id , sc.next_run_time, sc.next_run_date, ssc.[enabled] AS schedule_enabled
FROM msdb..sysjobschedules sc --uurib ka schedule on enabled
INNER JOIN [msdb]..[sysschedules] ssc ON (sc.[schedule_id] = ssc.[schedule_id])
WHERE EXISTS (SELECT job_id FROM @tood Tli WHERE Tli.job_id = sc.job_id )
) c ON (a.job_id = c.job_id)
INNER JOIN
(
SELECT DISTINCT J1.JOB_ID, J1.[MESSAGE],
[dbo].[SQLSERVERAGENTDATETIME_KUIDO](J1.RUN_DATE,J1.RUN_TIME) AS LAST_RUN_TIME,
J1.RUN_STATUS, J1.RUN_DURATION
FROM msdb.dbo.sysjobhistory J1 WHERE J1.step_id=0
AND job_id IN (SELECT job_id FROM @tood Tli )
AND ( [dbo].[SQLSERVERAGENTDATETIME_KUIDO](J1.RUN_DATE,J1.RUN_TIME) =
( SELECT MAX([dbo].[SQLSERVERAGENTDATETIME_KUIDO](J2.RUN_DATE,J2.RUN_TIME) )
FROM msdb.dbo.sysjobhistory J2 WHERE J1.[job_id] = J2.JOB_ID AND J2.step_id=0) )
) Hist ON (a.job_id = Hist.JOB_ID )
ORDER BY B.JOB_NAME
/*
LAST_RUN_STATUS
0 Failed
1 Succeeded
2 Retry (step only)
3 Canceled
4 In-progress message
5 Unknown
*/
END
1. Töö ise olema lubatud
2. Töö enda plaanur olema lubatud
Kuna mõnikord unustad selle märkeruudu "Enabled" peale sättida siis abiks SP mis teeb ülevaate SQL Agenti andmebaasi töödest.
ENABLED väli näitab kas töö on peatatud
SCHEDULE_ENABLED väli näitab kas töö plaanur on peatatud
[dbo].[SQLSERVERAGENTDATETIME_KUIDO] funktsiooni ma olen kirjeldanud
varasemalt siin http://kuidoveeb.blogspot.com/2009/04/sql-server-agent-kuupaeva-funktsioon.html
Parameeter @job_names võimaldab filtreerida töö nime alguse järgi
-- =============================================
-- Description: Andmebaasi tööde nimekiri
-- =============================================
CREATE PROCEDURE [dbo].[WINTIME_JOBS_KUIDO_S]
@job_names NVARCHAR(128)=N'MINUTOOD'
WITH EXECUTE AS 'DBO' --käivitame teatud kasutaja õigustes kuna pole mõtet and igaühele otse tabelitele juurdepääsu
AS
BEGIN
SET NOCOUNT ON
DECLARE @err INT
IF RIGHT(@job_names,1) <> '%'
SET @job_names=@job_names+'%'
--OTSIME KÕIGEPEALT SOBIVAD TÖÖD VÄLJA (filter nime alguse järgi)
DECLARE @tood TABLE (job_id UNIQUEIDENTIFIER PRIMARY KEY, job_name NVARCHAR(128) COLLATE DATABASE_DEFAULT, enabled TINYINT,
job_owner NVARCHAR(128) COLLATE DATABASE_DEFAULT NULL )
INSERT INTO @tood (job_id, job_name, [enabled] , job_owner)
SELECT sj.JOB_ID, sj.NAME, sj.[enabled],su.name FROM [msdb]..sysjobs sj
LEFT JOIN msdb..[SYSUSERS] su ON (sj.owner_sid = su.sid )
WHERE sj.name LIKE @job_names
--TEEME ÜLEVAATE
SELECT ISNULL(b.job_owner,'') AS job_owner, b.job_name, b.job_id, b.[enabled]
,[dbo].[SQLSERVERAGENTDATETIME_KUIDO](c.next_run_date,c.next_run_time) AS NEXT_RUN_TIME
,a.step_name, a.subsystem, a.command, a.database_name
,a.step_id, a.step_name, c.schedule_enabled
,Hist.[MESSAGE] AS LAST_RUN_MESSAGE, Hist.LAST_RUN_TIME
,Hist.[RUN_DURATION] AS LAST_RUN_DURATION, Hist.RUN_STATUS AS LAST_RUN_STATUS
FROM msdb..sysjobsteps a
INNER JOIN @tood b ON ( a.job_id =b.job_id )
INNER JOIN (SELECT sc.job_id , sc.next_run_time, sc.next_run_date, ssc.[enabled] AS schedule_enabled
FROM msdb..sysjobschedules sc --uurib ka schedule on enabled
INNER JOIN [msdb]..[sysschedules] ssc ON (sc.[schedule_id] = ssc.[schedule_id])
WHERE EXISTS (SELECT job_id FROM @tood Tli WHERE Tli.job_id = sc.job_id )
) c ON (a.job_id = c.job_id)
INNER JOIN
(
SELECT DISTINCT J1.JOB_ID, J1.[MESSAGE],
[dbo].[SQLSERVERAGENTDATETIME_KUIDO](J1.RUN_DATE,J1.RUN_TIME) AS LAST_RUN_TIME,
J1.RUN_STATUS, J1.RUN_DURATION
FROM msdb.dbo.sysjobhistory J1 WHERE J1.step_id=0
AND job_id IN (SELECT job_id FROM @tood Tli )
AND ( [dbo].[SQLSERVERAGENTDATETIME_KUIDO](J1.RUN_DATE,J1.RUN_TIME) =
( SELECT MAX([dbo].[SQLSERVERAGENTDATETIME_KUIDO](J2.RUN_DATE,J2.RUN_TIME) )
FROM msdb.dbo.sysjobhistory J2 WHERE J1.[job_id] = J2.JOB_ID AND J2.step_id=0) )
) Hist ON (a.job_id = Hist.JOB_ID )
ORDER BY B.JOB_NAME
/*
LAST_RUN_STATUS
0 Failed
1 Succeeded
2 Retry (step only)
3 Canceled
4 In-progress message
5 Unknown
*/
END
neljapäev, 1. oktoober 2009
XML välja sisu ilusaks ajamine peale sql:variable-ga mudimist
Selline juhtum, kui on vaja SQL SERVER-i XML muutujat vahepeal muuta no näiteks
DECLARE @aop XML, @lep INT, @relcon NVARCHAR(2000)
SET @relcon=''+CAST(@contractId AS NVARCHAR(20))+' '
SET @lep = @aop.value('/RELATED_CONTRACT[1]', 'INT')
IF @lep IS NULL --KUI RELATED_CONTRACT on puudu, lisame vastava NODE
SET @aop.modify('insert text{sql:variable("@relcon")} as last into (/Options)[1]')
kui nüüd SQL SERVER manageriga seda @aop sisu vaadata on seal '<' asemel
mis ei ole üldsegi ilus, et see asi korda saada tuleb stringitöötlust teha, XML muutuja pöörata NVARCHAR(MAX), muuta ära ja pöörata XML-iks tagasi
Kui tahad XML välja RAISERRORIGA ekraanile lasta, siis tuleb samuti stringitöötlust teha
SET @relcon = REPLACE(CAST(@aop AS NVARCHAR(4000)),'<','_')
RAISERROR('XML info %s',16,1,@relcon)
ASP.NET tõlgendab ju '<' algavaid asju kui HTML-i elemente mis tegelikult ongi õige
DECLARE @aop XML, @lep INT, @relcon NVARCHAR(2000)
SET @relcon='
SET @lep = @aop.value('/RELATED_CONTRACT[1]', 'INT')
IF @lep IS NULL --KUI RELATED_CONTRACT on puudu, lisame vastava NODE
SET @aop.modify('insert text{sql:variable("@relcon")} as last into (/Options)[1]')
kui nüüd SQL SERVER manageriga seda @aop sisu vaadata on seal '<' asemel
mis ei ole üldsegi ilus, et see asi korda saada tuleb stringitöötlust teha, XML muutuja pöörata NVARCHAR(MAX), muuta ära ja pöörata XML-iks tagasi
Kui tahad XML välja RAISERRORIGA ekraanile lasta, siis tuleb samuti stringitöötlust teha
SET @relcon = REPLACE(CAST(@aop AS NVARCHAR(4000)),'<','_')
RAISERROR('XML info %s',16,1,@relcon)
ASP.NET tõlgendab ju '<' algavaid asju kui HTML-i elemente mis tegelikult ongi õige
esmaspäev, 21. september 2009
Delegaadil põhinev andmevahetus usercontrolite vahel
Tegelikult ei soovitata nii teha aga kui harva tuleb sellised asju ette siis hea lihtne meeles pidada.
Definitsioonide nimetused võivad siis postituses segamini olla.
Veebilehel on mitu usercontroli ja tahad, et näiteks kui GridView peal klikid seda Select nuppu siis tahad, et selle tulemusena mingil teisel usercontrolil midagi juhtuks.
Gridview Select nupu saab teha niimoodi
Usercontroli Code-behindis defineerib delegaadi ja eventi mille külge saavad teised controlid end külge pookida, kui asja peaks olema. UserControli nimi on näiteks OtsiKohamaara
public event ValitiKorter KorterValiti; //see event saadab välja ValitiKorter(int indeks) delegaati
public delegate void ValitiKorter(int indeks);
GridView SelectedIndexChanged SelectedIndexChanged event, mis hakkab seda delegaati välja saatma:
protected void GridViewKorterid_SelectedIndexChanged(object sender, EventArgs e)
{
GridViewRow se = this.GridViewKorterid.SelectedRow;
if ( se != null)
{
if (KorterValiti != null) // kas on keegi ennast külge pannud, et sellele SelectedIndexChanged reageerida
{
KorterValiti(Convert.ToInt32(this.GridViewKorterid.SelectedDataKey.Value));
}
}
}
Kuida asja tarbida teise veebilehe peal, kõigepealt registreerime ennast delegaati vastu võtma.
protected void Page_Load(object sender, EventArgs e)
{
//OtsiKohamaara1 on nüüd see UserControl lehe peal mille Select nupu kliki tahame kinni püüda
//see tuleb iga kord PostBackist sõltumata, muidu unustab ära
this.OtsiKohamaara1.KorterValiti += new UserControl_OtsiKohamaara.ValitiKorter(OtsiKohamaara1_KorterValiti);
if (!IsPostBack)
{
}
}
ja meetod, mis selle delegaadiga tegelema hakkab.
// kui OtsiKohamaara korter valitakse, siis tuleb sealt delegaat
void OtsiKohamaara1_KorterValiti(int indeks)
{
//indeks on nüüd see int väärtus, mis usercontroli poolt teele saadetakse
// ja siin saab juba asju edasi teha
this.LiteralFlatId.Text = indeks.ToString();
}
Definitsioonide nimetused võivad siis postituses segamini olla.
Veebilehel on mitu usercontroli ja tahad, et näiteks kui GridView peal klikid seda Select nuppu siis tahad, et selle tulemusena mingil teisel usercontrolil midagi juhtuks.
Gridview Select nupu saab teha niimoodi
Usercontroli Code-behindis defineerib delegaadi ja eventi mille külge saavad teised controlid end külge pookida, kui asja peaks olema. UserControli nimi on näiteks OtsiKohamaara
public event ValitiKorter KorterValiti; //see event saadab välja ValitiKorter(int indeks) delegaati
public delegate void ValitiKorter(int indeks);
GridView SelectedIndexChanged SelectedIndexChanged event, mis hakkab seda delegaati välja saatma:
protected void GridViewKorterid_SelectedIndexChanged(object sender, EventArgs e)
{
GridViewRow se = this.GridViewKorterid.SelectedRow;
if ( se != null)
{
if (KorterValiti != null) // kas on keegi ennast külge pannud, et sellele SelectedIndexChanged reageerida
{
KorterValiti(Convert.ToInt32(this.GridViewKorterid.SelectedDataKey.Value));
}
}
}
Kuida asja tarbida teise veebilehe peal, kõigepealt registreerime ennast delegaati vastu võtma.
protected void Page_Load(object sender, EventArgs e)
{
//OtsiKohamaara1 on nüüd see UserControl lehe peal mille Select nupu kliki tahame kinni püüda
//see tuleb iga kord PostBackist sõltumata, muidu unustab ära
this.OtsiKohamaara1.KorterValiti += new UserControl_OtsiKohamaara.ValitiKorter(OtsiKohamaara1_KorterValiti);
if (!IsPostBack)
{
}
}
ja meetod, mis selle delegaadiga tegelema hakkab.
// kui OtsiKohamaara korter valitakse, siis tuleb sealt delegaat
void OtsiKohamaara1_KorterValiti(int indeks)
{
//indeks on nüüd see int väärtus, mis usercontroli poolt teele saadetakse
// ja siin saab juba asju edasi teha
this.LiteralFlatId.Text = indeks.ToString();
}
teisipäev, 25. august 2009
GridView ridade kokkusummeerimine Contentpage ja UpdatePanel-i sees .NET Framework 3.5 SP1
Kui on Masterpage sees asp:Content lehekülg mille see on UpdatePanel ja selle sees GridView võib juhtuda, et
GridView RowDataBound kutsutakse kaks korda välja, kusjuures mõnel serveril töötab korralikult mõnel aga mitte, täitsa kuidas juhtub.
Kui nüüd summerida GridView RowDataBound eventis mingeid väärtusi kokku võib saada topelt tulemuse ja juhtub see täiesti suvaliselt
if (e.Row.RowType == DataControlRowType.DataRow)
{
this.tsumma += Convert.ToDecimal(((System.Data.DataRowView)e.Row.DataItem)["total_summa"]);
}
if (e.Row.RowType == DataControlRowType.Footer)
{
e.Row.Cells[2].Text = Resources.Resource.Total;
e.Row.Cells[3].Text = String.Format("{0:F2}", this.tsumma);
}
Siin võib juhtuda, et summa on tegelikult kahekordselt arvutatud.
Lahendusena võib summerimise tuua GridView DataBound eventisse
this.tsumma=0;
foreach (GridViewRow rida in this.GridViewArved.Rows)
{
if (rida.RowType == DataControlRowType.DataRow)
{
Label rs = (Label)rida.FindControl("LabelArveSumma");
if (rs != null)
{
this.tsumma += Convert.ToDecimal(rs.Text.Trim());
}
}
}
if (this.GridViewArved.FooterRow != null)
{
this.GridViewArved.FooterRow.Cells[2].Text = Resources.Resource.Total;
this.GridViewArved.FooterRow.Cells[3].Text = String.Format("{0:F2}", this.tsumma);
}
LabelArveSumma on GridView TeplateField-is olev WebControl
<asp:TemplateField SortExpression="total_summa" HeaderText="<%$ Resources:resource, InvoiceTotal %>">
<ItemTemplate>
<asp:Label ID="LabelArveSumma" runat="server"
Text='<%# Eval("total_summa", "{0:F2}") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
GridView RowDataBound kutsutakse kaks korda välja, kusjuures mõnel serveril töötab korralikult mõnel aga mitte, täitsa kuidas juhtub.
Kui nüüd summerida GridView RowDataBound eventis mingeid väärtusi kokku võib saada topelt tulemuse ja juhtub see täiesti suvaliselt
if (e.Row.RowType == DataControlRowType.DataRow)
{
this.tsumma += Convert.ToDecimal(((System.Data.DataRowView)e.Row.DataItem)["total_summa"]);
}
if (e.Row.RowType == DataControlRowType.Footer)
{
e.Row.Cells[2].Text = Resources.Resource.Total;
e.Row.Cells[3].Text = String.Format("{0:F2}", this.tsumma);
}
Siin võib juhtuda, et summa on tegelikult kahekordselt arvutatud.
Lahendusena võib summerimise tuua GridView DataBound eventisse
this.tsumma=0;
foreach (GridViewRow rida in this.GridViewArved.Rows)
{
if (rida.RowType == DataControlRowType.DataRow)
{
Label rs = (Label)rida.FindControl("LabelArveSumma");
if (rs != null)
{
this.tsumma += Convert.ToDecimal(rs.Text.Trim());
}
}
}
if (this.GridViewArved.FooterRow != null)
{
this.GridViewArved.FooterRow.Cells[2].Text = Resources.Resource.Total;
this.GridViewArved.FooterRow.Cells[3].Text = String.Format("{0:F2}", this.tsumma);
}
LabelArveSumma on GridView TeplateField-is olev WebControl
<asp:TemplateField SortExpression="total_summa" HeaderText="<%$ Resources:resource, InvoiceTotal %>">
<ItemTemplate>
<asp:Label ID="LabelArveSumma" runat="server"
Text='<%# Eval("total_summa", "{0:F2}") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
Blogged with the Flock Browser
kolmapäev, 29. juuli 2009
Sys.Net.WebRequest klassiga kliendi sertifikaadi küsimine kasutades Request.ClientCertificate meetodit
Vaja lisada andmete sisestusvormile nupp, millega saab osa vormil nõutavaid andmeid lugeda ID-kaardi pealt, kuid nii, et vormi teistele väljadele sisestatud info jääks peale ID-kaardilt andmete lugemist alles(ei tee tervele lehele Postbacki). See asi on võimalik lahendada .NET 3.5 AJAX-i Sys.Net.WebRequest klassi kasutades
Vorm näiteks selline, kus isikukoodi, ees- ja perekonnanime võib lugeda ID-kaardi pealt ja muu info tuleb käsitsi sisestada
ID-kaardilt saame andmed kätte tehes algselt lehelt WebRequest.invoke() GET requesti päringu lehele Idkaart.aspx, kus Request.ClientCertificate meetodiga loeme
ID-kaardilt andmed ja saadame nad tagasi püstkriipsuga eraldatud stringijadana Response.Write("Isikukood|Perekonnanimi|Eesnimi");
IIS-i poolt tuleb Idkaart.aspx lehel peale seada, et Accept Client certificate, siis pöördumisel
Idkaart.aspx poole küsitakse kliendi sertifikaati, ehk ID-kaardi puhul tuleb PIN1 sisestada
NB! Kui kasutatakse Sertifitseerimiskeskuse serte, siis nii JUUR-SK kui ka KLASS3-SK serdid peavad olema õieti paigaldatud, vastasel juhul Request.ClientCertificate ei pruugi tööle hakata
Idkaart.aspx lehe sisu selline, sealt loeme ID-kaardi andmed
public partial class IdKaart : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string inf="";
try
{
//küsime kliendi sertifikaati
HttpClientCertificate sert = Request.ClientCertificate;
if (sert.IsPresent) //kui sertifikaat on olemas
{
if (System.DateTime.Now < sert.ValidUntil) //kas kehtib veel
{
String unparsed = sert.Subject;
System.Text.RegularExpressions.Regex re = new Regex("SERIALNUMBER=(\\d{11})");
if (re.IsMatch(unparsed))
{
if (re.Match(unparsed).Groups[1].Value.Length == 11) //isikukood peab olema 11 sümbolit pikk
{
inf = re.Match(unparsed).Groups[1].Value + "|"; //isikukood
}
}
System.Text.RegularExpressions.Regex rename = new Regex("SN=(.*?),\\s+G=(.*?),");
if (rename.IsMatch(unparsed))
{
inf += rename.Match(unparsed).Groups[1].Value+"|"; //perekonnanimi
inf += rename.Match(unparsed).Groups[2].Value; //eesnimi
}
}
}
}
catch (SystemException ex)
{ }
//tagastame eraldatud stringijada isikukood|perekonnanimi|eesnimi
Response.Clear();
Response.BufferOutput = false;
Response.ContentType = "text/plain";
Response.ContentEncoding = System.Text.ASCIIEncoding.Default;
Response.Write(inf);
Response.End();
}
}
leht XMLHttpParing.aspx, kus andmeid küsime näeb välja selline, kasutada tuleb Javaskripti, mis WebRequest.invoke() meetodiga pöördub lehelt IdKaart.aspx andmeid lugema ja kui on sealt
andmed kätte saanud, siis täidab osad sisestusväljad ära ja keelab nende edasise kasutamine
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="XMLHttpParing.aspx.cs" Inherits="ASP_DEMO.XMLHttpParing" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>XMLHttpPäring</title>
<script type="text/javascript">
var xmlreq;
function pagLoad() {
try {
var webRequest = new Sys.Net.WebRequest();
webRequest.set_url("IdKaart.aspx");
webRequest.set_httpVerb("GET");
webRequest.add_completed(completedHandler);
webRequest.invoke();
}
catch (err)
{ }
}
function completedHandler(result, eventArgs) {
if (result.get_responseAvailable()) {
var vastus = new Array();
vastus = result.get_responseData().split("|");
if (vastus.length == 3) {
var nimi = document.getElementById("<%= TextBoxPerenimi.ClientID %>");
nimi.value = vastus[1];
nimi.disabled = true; //kui tuleb andmeid ID-kaardilt, siis keelab edasise tekstivälja muutmise ära
nimi = document.getElementById("<%= TextBoxEesnimi.ClientID %>");
nimi.value = vastus[2];
nimi.disabled = true;
nimi = document.getElementById("<%= TextBoxIsikukood.ClientID %>");
nimi.value = vastus[0];
nimi.disabled = true;
nimi = document.getElementById("<%= ButtonIdkaart.ClientID %>");
nimi.disabled = true;
}
}
}
</script>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel runat="server" ID="UpdatePanel1">
<ContentTemplate>
<table>
<tr>
<td>Isikukood <asp:TextBox ID="TextBoxIsikukood" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td>Perekonnanimi <asp:TextBox ID="TextBoxPerenimi" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td>Eesnimi <asp:TextBox ID="TextBoxEesnimi" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td style="width:200px">Muu info(tekst, mis ID kaardilt andmete küsimise järel jääb vormile alles<asp:TextBox ID="TextBoxMuu" MaxLength="400" Rows="4" Columns="70"
runat="server" TextMode="MultiLine"></asp:TextBox>
</td>
</tr>
</table>
<div>
<asp:Button ID="ButtonIdkaart" CausesValidation="false" runat="server"
Text="Loe andmed ID-kaardilt" />
<asp:Button ID="ButtonEdasi" runat="server" Text="Edasi" />
</div>
</ContentTemplate>
</asp:UpdatePanel>
</form>
</body>
</html>
code-behind XMLHttpParing.aspx lehele
public partial class XMLHttpParing : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//paneme kliendi poolse javascripti külge, tuleb kasutada return pagLoad(),
// kui ainult pagLoad() onClick eventile külge panna, teeb leht Postbacki ja
// webRequest.invoke()-iga loetud andmed korra vilksatavad ekraanil ja siis kaovad
this.ButtonIdkaart.Attributes.Add("onClick", "return pagLoad()");
}
}
pagLoad() on see isetehtud Javaskripti funktsioon, mille välja kutsume ja mis selle AJAX-I XMLHttpRequest päringu ära teeb.
function completedHandler() on see Javaskripti funktsioon, mis IdKaart.aspx lehelt info vastu võtab, töötleb ja kontrollib neid ning viib saadud andmed vormile.
Pikemalt on Windowsi Certificate Services Client-ist mille kaudu ID-kaardi majandmine
käib juttu siin.
http://technet.microsoft.com/en-us/library/cc700848.aspx
Vorm näiteks selline, kus isikukoodi, ees- ja perekonnanime võib lugeda ID-kaardi pealt ja muu info tuleb käsitsi sisestada
ID-kaardilt saame andmed kätte tehes algselt lehelt WebRequest.invoke() GET requesti päringu lehele Idkaart.aspx, kus Request.ClientCertificate meetodiga loeme
ID-kaardilt andmed ja saadame nad tagasi püstkriipsuga eraldatud stringijadana Response.Write("Isikukood|Perekonnanimi|Eesnimi");
IIS-i poolt tuleb Idkaart.aspx lehel peale seada, et Accept Client certificate, siis pöördumisel
Idkaart.aspx poole küsitakse kliendi sertifikaati, ehk ID-kaardi puhul tuleb PIN1 sisestada
NB! Kui kasutatakse Sertifitseerimiskeskuse serte, siis nii JUUR-SK kui ka KLASS3-SK serdid peavad olema õieti paigaldatud, vastasel juhul Request.ClientCertificate ei pruugi tööle hakata
Idkaart.aspx lehe sisu selline, sealt loeme ID-kaardi andmed
public partial class IdKaart : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string inf="";
try
{
//küsime kliendi sertifikaati
HttpClientCertificate sert = Request.ClientCertificate;
if (sert.IsPresent) //kui sertifikaat on olemas
{
if (System.DateTime.Now < sert.ValidUntil) //kas kehtib veel
{
String unparsed = sert.Subject;
System.Text.RegularExpressions.Regex re = new Regex("SERIALNUMBER=(\\d{11})");
if (re.IsMatch(unparsed))
{
if (re.Match(unparsed).Groups[1].Value.Length == 11) //isikukood peab olema 11 sümbolit pikk
{
inf = re.Match(unparsed).Groups[1].Value + "|"; //isikukood
}
}
System.Text.RegularExpressions.Regex rename = new Regex("SN=(.*?),\\s+G=(.*?),");
if (rename.IsMatch(unparsed))
{
inf += rename.Match(unparsed).Groups[1].Value+"|"; //perekonnanimi
inf += rename.Match(unparsed).Groups[2].Value; //eesnimi
}
}
}
}
catch (SystemException ex)
{ }
//tagastame eraldatud stringijada isikukood|perekonnanimi|eesnimi
Response.Clear();
Response.BufferOutput = false;
Response.ContentType = "text/plain";
Response.ContentEncoding = System.Text.ASCIIEncoding.Default;
Response.Write(inf);
Response.End();
}
}
leht XMLHttpParing.aspx, kus andmeid küsime näeb välja selline, kasutada tuleb Javaskripti, mis WebRequest.invoke() meetodiga pöördub lehelt IdKaart.aspx andmeid lugema ja kui on sealt
andmed kätte saanud, siis täidab osad sisestusväljad ära ja keelab nende edasise kasutamine
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="XMLHttpParing.aspx.cs" Inherits="ASP_DEMO.XMLHttpParing" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>XMLHttpPäring</title>
<script type="text/javascript">
var xmlreq;
function pagLoad() {
try {
var webRequest = new Sys.Net.WebRequest();
webRequest.set_url("IdKaart.aspx");
webRequest.set_httpVerb("GET");
webRequest.add_completed(completedHandler);
webRequest.invoke();
}
catch (err)
{ }
}
function completedHandler(result, eventArgs) {
if (result.get_responseAvailable()) {
var vastus = new Array();
vastus = result.get_responseData().split("|");
if (vastus.length == 3) {
var nimi = document.getElementById("<%= TextBoxPerenimi.ClientID %>");
nimi.value = vastus[1];
nimi.disabled = true; //kui tuleb andmeid ID-kaardilt, siis keelab edasise tekstivälja muutmise ära
nimi = document.getElementById("<%= TextBoxEesnimi.ClientID %>");
nimi.value = vastus[2];
nimi.disabled = true;
nimi = document.getElementById("<%= TextBoxIsikukood.ClientID %>");
nimi.value = vastus[0];
nimi.disabled = true;
nimi = document.getElementById("<%= ButtonIdkaart.ClientID %>");
nimi.disabled = true;
}
}
}
</script>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel runat="server" ID="UpdatePanel1">
<ContentTemplate>
<table>
<tr>
<td>Isikukood <asp:TextBox ID="TextBoxIsikukood" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td>Perekonnanimi <asp:TextBox ID="TextBoxPerenimi" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td>Eesnimi <asp:TextBox ID="TextBoxEesnimi" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td style="width:200px">Muu info(tekst, mis ID kaardilt andmete küsimise järel jääb vormile alles<asp:TextBox ID="TextBoxMuu" MaxLength="400" Rows="4" Columns="70"
runat="server" TextMode="MultiLine"></asp:TextBox>
</td>
</tr>
</table>
<div>
<asp:Button ID="ButtonIdkaart" CausesValidation="false" runat="server"
Text="Loe andmed ID-kaardilt" />
<asp:Button ID="ButtonEdasi" runat="server" Text="Edasi" />
</div>
</ContentTemplate>
</asp:UpdatePanel>
</form>
</body>
</html>
code-behind XMLHttpParing.aspx lehele
public partial class XMLHttpParing : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//paneme kliendi poolse javascripti külge, tuleb kasutada return pagLoad(),
// kui ainult pagLoad() onClick eventile külge panna, teeb leht Postbacki ja
// webRequest.invoke()-iga loetud andmed korra vilksatavad ekraanil ja siis kaovad
this.ButtonIdkaart.Attributes.Add("onClick", "return pagLoad()");
}
}
pagLoad() on see isetehtud Javaskripti funktsioon, mille välja kutsume ja mis selle AJAX-I XMLHttpRequest päringu ära teeb.
function completedHandler() on see Javaskripti funktsioon, mis IdKaart.aspx lehelt info vastu võtab, töötleb ja kontrollib neid ning viib saadud andmed vormile.
Pikemalt on Windowsi Certificate Services Client-ist mille kaudu ID-kaardi majandmine
käib juttu siin.
http://technet.microsoft.com/en-us/library/cc700848.aspx
Blogged with the Flock Browser
neljapäev, 23. juuli 2009
URL RequestFiltering koos ReportViewer Controliga IIS7 peal
IIS7 on veebirakendustele selline tore sisseehitatud võimalus filtreerida GET päringuid URL andmete järgi, ehk rakenduse web.config failis, saab requestFiltering filtering osas ära määrata, kui pikk saab olla maksimaalne
URL ja kui pikk saab olla QUERYSTRING. Aitab näiteks SQL injektsiooni rünnakute vastu.
Kui on ka kasutusel ReportViewer aruannete tegemiseks, tuleb arvestada, et see ReportViewer ise teeb ka palju GET päringuid, mis isenesest võivad olla päris pika QUEYSTRING-iga näiteks
URI: /Reserved.ReportViewerWebControl.axd?Mode=true&ReportID=56afacf3f4c74cd69af397d2b8eefc0b&ControlID=a64ab41370cf4a28ba5967b952cf9038&Culture=1061&UICulture=1061&ReportStack=1&OpType=ReportImage&StreamID=148c7b15-8020-4ce4-9e17-a48043495af8
Otstarbekam on nüüd määrata eraldi web.configis reegel location elemendiga ReportViewerile näiteks niimoodi:
URL ja kui pikk saab olla QUERYSTRING. Aitab näiteks SQL injektsiooni rünnakute vastu.
Kui on ka kasutusel ReportViewer aruannete tegemiseks, tuleb arvestada, et see ReportViewer ise teeb ka palju GET päringuid, mis isenesest võivad olla päris pika QUEYSTRING-iga näiteks
URI: /Reserved.ReportViewerWebControl.axd?Mode=true&ReportID=56afacf3f4c74cd69af397d2b8eefc0b&ControlID=a64ab41370cf4a28ba5967b952cf9038&Culture=1061&UICulture=1061&ReportStack=1&OpType=ReportImage&StreamID=148c7b15-8020-4ce4-9e17-a48043495af8
Otstarbekam on nüüd määrata eraldi web.configis reegel location elemendiga ReportViewerile näiteks niimoodi:
kolmapäev, 22. juuli 2009
Muutujat kasutava SQL päringu kiirendamine OPTION(RECOMPILE) kasutamisega
Üks päring millega päev otsa vaeva nägin. Tehtud täitsa mõistlik SP, mille sees üks päring
DECLARE @apref VARCHAR(1)
SET @apref='C'
SELECT ACCOUNT.ID FROM DBO.ACCOUNT WHERE NOT EXISTS
( SELECT fd.[inv_no] FROM [dbo].[Cust_ Ledger Entry] fd WHERE
fd.[inv_no] = @apref+CAST(ACCOUNT.ID AS VARCHAR(30)) ) AND ACCOUNT.
W_SENT IS NOT NULL
mis töötab aga jube aegalselt
kui päring muuta lihtsalt ilma muutuja kasutamiseta päringuks
SELECT ACCOUNT.ID FROM DBO.ACCOUNT WHERE NOT EXISTS
( SELECT fd.[inv_no] FROM [dbo].[Cust_ Ledger Entry] fd WHERE
fd.[inv_no] = 'C'+CAST(ACCOUNT.ID AS VARCHAR(30)) ) AND ACCOUNT.
W_SENT IS NOT NULL
on asi kiire
Probleem selles, et SQL SERVER-i optimisaator teeb tervele SP-le optimiseerimise ja
SELECT lause koha peal ta ei tea mis on @apref väärtus ja üritab seda pimesi arvata
Üks võimalus on teha dünaamiline SQL aga parem on kasutada OPTION(RECOMPILE) SELECT lause juures
SELECT ACCOUNT.ID FROM DBO.ACCOUNT WHERE NOT EXISTS
( SELECT fd.[inv_no] FROM [dbo].[Cust_ Ledger Entry] fd WHERE
fd.[inv_no] = @apref+CAST(ACCOUNT.ID AS VARCHAR(30)) ) AND ACCOUNT.
W_SENT IS NOT NULL OPTION(RECOMPILE)
sel juhul optimisaator vaatab muutja @apref väärtust päringu tegemise hetkel ja päring läheb kiireks
Asja lahendamise juures olid abiks SQLMONSTERi inimesed
http://www.sqlmonster.com/Uwe/Forum.aspx/sql-server-performance/331/Variable-in-SELECT-expression-causes-query-degradation
DECLARE @apref VARCHAR(1)
SET @apref='C'
SELECT ACCOUNT.ID FROM DBO.ACCOUNT WHERE NOT EXISTS
( SELECT fd.[inv_no] FROM [dbo].[Cust_ Ledger Entry] fd WHERE
fd.[inv_no] = @apref+CAST(ACCOUNT.ID AS VARCHAR(30)) ) AND ACCOUNT.
W_SENT IS NOT NULL
mis töötab aga jube aegalselt
kui päring muuta lihtsalt ilma muutuja kasutamiseta päringuks
SELECT ACCOUNT.ID FROM DBO.ACCOUNT WHERE NOT EXISTS
( SELECT fd.[inv_no] FROM [dbo].[Cust_ Ledger Entry] fd WHERE
fd.[inv_no] = 'C'+CAST(ACCOUNT.ID AS VARCHAR(30)) ) AND ACCOUNT.
W_SENT IS NOT NULL
on asi kiire
Probleem selles, et SQL SERVER-i optimisaator teeb tervele SP-le optimiseerimise ja
SELECT lause koha peal ta ei tea mis on @apref väärtus ja üritab seda pimesi arvata
Üks võimalus on teha dünaamiline SQL aga parem on kasutada OPTION(RECOMPILE) SELECT lause juures
SELECT ACCOUNT.ID FROM DBO.ACCOUNT WHERE NOT EXISTS
( SELECT fd.[inv_no] FROM [dbo].[Cust_ Ledger Entry] fd WHERE
fd.[inv_no] = @apref+CAST(ACCOUNT.ID AS VARCHAR(30)) ) AND ACCOUNT.
W_SENT IS NOT NULL OPTION(RECOMPILE)
sel juhul optimisaator vaatab muutja @apref väärtust päringu tegemise hetkel ja päring läheb kiireks
Asja lahendamise juures olid abiks SQLMONSTERi inimesed
http://www.sqlmonster.com/Uwe/Forum.aspx/sql-server-performance/331/Variable-in-SELECT-expression-causes-query-degradation
reede, 3. juuli 2009
Andmebaasi stuktuuri kaitsmine VIEW DEFINITION õiguse keelamisega PUBLIC rollil
Iga kasutaja, mis MS SQL SERVER-il tehakse ja kellele antakse ligipääs mingile andmebaasile pannaks vaikimisi ka selle andmebaasi PUBLIC rolli. Mille tulemusena saab kasutaja näha, mis protseduurid ja tabelid selles andmebaasis olemas on, ehk näha andmebaasi struktuuri kirjeldust.
Rakenduse toimimiseks ei pruugi aga andmebaasi struktuuri kirjelduse teada olemine üldse vajalik olla. Seda saab piirata, kui keelata andmebaasi PUBLIC rollil VIEW DEFINITION õigus.
DENY VIEW DEFINITION TO public
Lõpeb nüüd asi sellega, et kui kasutaja baasi sisu vaatab ei näe ta sealt midagi. Avab näiteks Management Studioga baasi aga seal ei näita baasi struktuurist mitte kui midagi
Isegi, kui temale on andmebaasisi DB_OWNER õigused antud, siis saab ta näha vaid tabelite sturkuuri aga ei saa tabelite struktuuri muuta.
Saab veateate Tabel TABELINIMI is set to read only, user doesn't have enough rights on this table
Kõrvalnäht, mis kaasneb Visual Studio2008 kasutamisega on see, et kui projektis on datasetid (xsd failid) siis seal sees tabeladapterite muutmisel ei näidata näiteks enam salvestatud protseduuride nimekirja.
Õiguse saab tagasi panna
GRANT VIEW DEFINITION TO public
Rakenduse toimimiseks ei pruugi aga andmebaasi struktuuri kirjelduse teada olemine üldse vajalik olla. Seda saab piirata, kui keelata andmebaasi PUBLIC rollil VIEW DEFINITION õigus.
DENY VIEW DEFINITION TO public
Lõpeb nüüd asi sellega, et kui kasutaja baasi sisu vaatab ei näe ta sealt midagi. Avab näiteks Management Studioga baasi aga seal ei näita baasi struktuurist mitte kui midagi
Isegi, kui temale on andmebaasisi DB_OWNER õigused antud, siis saab ta näha vaid tabelite sturkuuri aga ei saa tabelite struktuuri muuta.
Saab veateate Tabel TABELINIMI is set to read only, user doesn't have enough rights on this table
Kõrvalnäht, mis kaasneb Visual Studio2008 kasutamisega on see, et kui projektis on datasetid (xsd failid) siis seal sees tabeladapterite muutmisel ei näidata näiteks enam salvestatud protseduuride nimekirja.
Õiguse saab tagasi panna
GRANT VIEW DEFINITION TO public
kolmapäev, 10. juuni 2009
ReportVieweri kasutamine IIS7 ja Windows Server 2008 korral
Kui ReportVieweri väljatrükil ekraanil on "tühi" või ei tule üldse ette
siis asja tööle seadmiseks
Variant A:
tuleb IIS Magnageriga (Application Pools) rakenduse basseini Managed Pipeline Mode seada "Classic" peale
Variant B tuleb basseini Intergated Mode korral rakenduse HandlerMappings menüüst käsitsi Add Managed Handler menüüpunkti abil ReportVieweri handler lisada, selleks:
Request Path ja Name koha peale kirjuta Reserved.ReportViewerWebControl.axd
Type: vali menüüst Microsoft.Reporting .., Microsoft.ReportViewer ..
siis asja tööle seadmiseks
Variant A:
tuleb IIS Magnageriga (Application Pools) rakenduse basseini Managed Pipeline Mode seada "Classic" peale
Variant B tuleb basseini Intergated Mode korral rakenduse HandlerMappings menüüst käsitsi Add Managed Handler menüüpunkti abil ReportVieweri handler lisada, selleks:
Request Path ja Name koha peale kirjuta Reserved.ReportViewerWebControl.axd
Type: vali menüüst Microsoft.Reporting .., Microsoft.ReportViewer ..
Blogged with the Flock Browser
reede, 29. mai 2009
SQL SERVER UDF funktsiooni teksti sisust parameetri vaikeväärtuse teadasaamine
Kui süsteemis on kasutusel meetod, kus mingi asja käitumine sõltub näiteks UDF funkstiooni parameetri väärtusest ja nüüd vaja teada
saada, kuidasmoodi see parameeter on seatud saab kasutada sellist
Funktsiooni päis ise, mille parameetrit teada tahame
ALTER FUNCTION [dbo].[VIITENUMBER]( @lepingu_nr INT, @arvenumber BIGINT, @meetod TINYINT=0 )
RETURNS NVARCHAR(30)
AS
...
ja siin @meetod TINYINT=0 vaikeväärtus määrab ära, kuidas süsteem peab käituma
siis selle väärtuse teadasaamiseks võib kasutada lähenemist, kus otsime funktsioon teksti sisust
DECLARE @t VARCHAR(8000), @Re INT
--leiame funktsiooni VIITENUMBER
SET @Re = ( SELECT TOP 1 ID FROM sys.sysobjects WHERE name = 'VIITENUMBER' AND XTYPE ='FN' )
--leiame tema sisu kirjelduse alguse
SET @t = ( SELECT LEFT(TEXT,8000) FROM sys.syscomments WHERE ID = @Re )
--otsime tema teksti kirjeldusest viitenumbri meetodi parameetri kohta
SET @Re=CHARINDEX('@meetod TINYINT=',@t)
--võtame antud kohast 3 tükki ja kuna on funktsiooni viimane parameeter siis lõpust ) eemaldame
SET @t = (SELECT REPLACE(SUBSTRING(@t,@Re+16,3),')','') )
ja @t väärtus peaks olema antud juhul '0', mida otsisimegi
saada, kuidasmoodi see parameeter on seatud saab kasutada sellist
Funktsiooni päis ise, mille parameetrit teada tahame
ALTER FUNCTION [dbo].[VIITENUMBER]( @lepingu_nr INT, @arvenumber BIGINT, @meetod TINYINT=0 )
RETURNS NVARCHAR(30)
AS
...
ja siin @meetod TINYINT=0 vaikeväärtus määrab ära, kuidas süsteem peab käituma
siis selle väärtuse teadasaamiseks võib kasutada lähenemist, kus otsime funktsioon teksti sisust
DECLARE @t VARCHAR(8000), @Re INT
--leiame funktsiooni VIITENUMBER
SET @Re = ( SELECT TOP 1 ID FROM sys.sysobjects WHERE name = 'VIITENUMBER' AND XTYPE ='FN' )
--leiame tema sisu kirjelduse alguse
SET @t = ( SELECT LEFT(TEXT,8000) FROM sys.syscomments WHERE ID = @Re )
--otsime tema teksti kirjeldusest viitenumbri meetodi parameetri kohta
SET @Re=CHARINDEX('@meetod TINYINT=',@t)
--võtame antud kohast 3 tükki ja kuna on funktsiooni viimane parameeter siis lõpust ) eemaldame
SET @t = (SELECT REPLACE(SUBSTRING(@t,@Re+16,3),')','') )
ja @t väärtus peaks olema antud juhul '0', mida otsisimegi
neljapäev, 21. mai 2009
SQL SERVER-i tabeli struktuuri kirjeldus koos väljade kirjeldusega
Kui sul on SQL SERVER-i tabel ja tabeli väljadele on lisatud kirjeldused siis see päring teeb välja nimi / kirjeldus väljavõtte
DECLARE @tabel NVARCHAR(128)
SET @tabel= 'TABELINIMI'
SELECT sc.column_name, CAST(extended_properties.value AS NVARCHAR(1000)) AS [description]
FROM (
SELECT isc.column_name , c.[object_id], c.column_id
FROM information_schema.columns isc
INNER JOIN sys.columns c ON isc.column_name = c.name
AND OBJECT_NAME(c.object_id) = @tabel
AND isc.table_name = @tabel
AND OBJECTPROPERTY(c.object_id, 'IsMsShipped')=0
) sc
LEFT JOIN sys.extended_properties ON (sc.[object_id] = extended_properties.major_id AND sc.[column_id] = extended_properties.minor_id)
ORDER BY sc.column_name
DECLARE @tabel NVARCHAR(128)
SET @tabel= 'TABELINIMI'
SELECT sc.column_name, CAST(extended_properties.value AS NVARCHAR(1000)) AS [description]
FROM (
SELECT isc.column_name , c.[object_id], c.column_id
FROM information_schema.columns isc
INNER JOIN sys.columns c ON isc.column_name = c.name
AND OBJECT_NAME(c.object_id) = @tabel
AND isc.table_name = @tabel
AND OBJECTPROPERTY(c.object_id, 'IsMsShipped')=0
) sc
LEFT JOIN sys.extended_properties ON (sc.[object_id] = extended_properties.major_id AND sc.[column_id] = extended_properties.minor_id)
ORDER BY sc.column_name
Blogged with the Flock Browser
kolmapäev, 20. mai 2009
SQL SERVER-ile ligipääsu piiramine IP aadressi põhiselt EVENTDATA() XML andmeid kasutades
Kui on ASP.NET veebirakendus istub serveril koos teiste SQL SERVER baasi kasutavate rakendustega ja SQL SERVER-i port on väljast lahti kuid enda rakendusel pöördumine andmebaasi käib ainult läbi veebirakenduse võib kasutada SQL SERVER-i LOGON trigerit, et piirata mujalt rakenduse andmebaasile ligipääsu. DDL LOGON trigeris uurib, kust ühenduti ja seejärel otsustab. Mõjub ainult nendele SQL LOGIN-ite mille vaikimisi andmebaas langeb kokku trigeris määratuga.
Nõuab SQL SERVER 2005 SP2 vähemalt. RAISERROR veateated lähevad ainult Serveri Application Event logisse. Kui IP aadress ei sobi saab sellise veateate:
Logon failed for login 'USERNAME' due to trigger execution
ALTER TRIGGER [KONTROLL_LOGON_CheckIP]
ON ALL SERVER
WITH EXECUTE AS 'sa' --kasutaja peab olema sysadmin fixed server role või ALTER TRACE õigusega kuna RAISERROR WITH LOG kasutame
FOR LOGON
AS
BEGIN
DECLARE @ev XML, @usr NVARCHAR(50), @ip NVARCHAR(35), @lubat INT, @defdb NVARCHAR(128)
SET @defdb='ABAASINIMI' --andmebaasi nimi, kus meil rakendus serveril sees on
SET @ev=(SELECT EVENTDATA())
SELECT @ip = @ev.value('(/EVENT_INSTANCE/ClientHost)[1]', 'NVARCHAR(35)') --kliendi IP aadress
,@usr=@ev.value('(/EVENT_INSTANCE/LoginName)[1]', 'NVARCHAR(50)') --kasutajanimi
IF @ip IS NULL --kui ühendutakse mingi muu protokolliga
RETURN
-- --uurime et on tegu SQL Loginiga ja on tegu LOGON tüüpi sündmusega
IF (SELECT @ev.value('(/EVENT_INSTANCE/LoginType)[1]', 'NVARCHAR(15)')) = 'SQL Login' --piirame ainult SQL Loginite ligipääsu
AND (SELECT @ev.value('(/EVENT_INSTANCE/EventType)[1]', 'NVARCHAR(15)')) = 'LOGON'
BEGIN
--kontrollime, kas on üldse ligipääs lubatud määratud andmebaasi, loginil peab olema @defdb baas määratud vaikimisi andmebaasiks
SET @lubat = (SELECT is_disabled FROM sys.sql_logins WITH (NOLOCK) WHERE name=@usr AND default_database_name=@defdb)
IF @lubat = 0 --kui antud SQL SERVER loginil on vaikimisi andmebaasile ligipääs lubatud
BEGIN
IF @ip NOT IN ('10.0.40.8') --Siia sulgudesse need IP aadressid, kust on lubatud ligipääs andmebaasile
BEGIN
RAISERROR('Ligipääs andmebaasile %s IP aadressilt %s on kasutajale %s keelatud',10,1,@defdb,@ip,@usr) WITH LOG --ka infona ka serveri Event Aplication Logi
ROLLBACK
--kui vaja kuskilegi kirja panna, et ligi ei saadud
--INSERT INTO [test].[dbo].[LOGI] (IPA, [EVENT]) VALUES (@ip,@ev)
RETURN
END
END
ELSE --kasutajal puudub vaikimisi juurdepääs määratud andmebaasile, mingi muu kasutaja
BEGIN
RAISERROR('Ligipääs vaikimisi andemebaasile %s IP addressilt %s on kasutajale %s keelatud',10,1,@defdb,@ip,@usr) WITH LOG --ka infona ka serveri Event Aplication Logi
ROLLBACK
RETURN
END
END
Nõuab SQL SERVER 2005 SP2 vähemalt. RAISERROR veateated lähevad ainult Serveri Application Event logisse. Kui IP aadress ei sobi saab sellise veateate:
Logon failed for login 'USERNAME' due to trigger execution
ALTER TRIGGER [KONTROLL_LOGON_CheckIP]
ON ALL SERVER
WITH EXECUTE AS 'sa' --kasutaja peab olema sysadmin fixed server role või ALTER TRACE õigusega kuna RAISERROR WITH LOG kasutame
FOR LOGON
AS
BEGIN
DECLARE @ev XML, @usr NVARCHAR(50), @ip NVARCHAR(35), @lubat INT, @defdb NVARCHAR(128)
SET @defdb='ABAASINIMI' --andmebaasi nimi, kus meil rakendus serveril sees on
SET @ev=(SELECT EVENTDATA())
SELECT @ip = @ev.value('(/EVENT_INSTANCE/ClientHost)[1]', 'NVARCHAR(35)') --kliendi IP aadress
,@usr=@ev.value('(/EVENT_INSTANCE/LoginName)[1]', 'NVARCHAR(50)') --kasutajanimi
IF @ip IS NULL --kui ühendutakse mingi muu protokolliga
RETURN
-- --uurime et on tegu SQL Loginiga ja on tegu LOGON tüüpi sündmusega
IF (SELECT @ev.value('(/EVENT_INSTANCE/LoginType)[1]', 'NVARCHAR(15)')) = 'SQL Login' --piirame ainult SQL Loginite ligipääsu
AND (SELECT @ev.value('(/EVENT_INSTANCE/EventType)[1]', 'NVARCHAR(15)')) = 'LOGON'
BEGIN
--kontrollime, kas on üldse ligipääs lubatud määratud andmebaasi, loginil peab olema @defdb baas määratud vaikimisi andmebaasiks
SET @lubat = (SELECT is_disabled FROM sys.sql_logins WITH (NOLOCK) WHERE name=@usr AND default_database_name=@defdb)
IF @lubat = 0 --kui antud SQL SERVER loginil on vaikimisi andmebaasile ligipääs lubatud
BEGIN
IF @ip NOT IN ('10.0.40.8') --Siia sulgudesse need IP aadressid, kust on lubatud ligipääs andmebaasile
BEGIN
RAISERROR('Ligipääs andmebaasile %s IP aadressilt %s on kasutajale %s keelatud',10,1,@defdb,@ip,@usr) WITH LOG --ka infona ka serveri Event Aplication Logi
ROLLBACK
--kui vaja kuskilegi kirja panna, et ligi ei saadud
--INSERT INTO [test].[dbo].[LOGI] (IPA, [EVENT]) VALUES (@ip,@ev)
RETURN
END
END
ELSE --kasutajal puudub vaikimisi juurdepääs määratud andmebaasile, mingi muu kasutaja
BEGIN
RAISERROR('Ligipääs vaikimisi andemebaasile %s IP addressilt %s on kasutajale %s keelatud',10,1,@defdb,@ip,@usr) WITH LOG --ka infona ka serveri Event Aplication Logi
ROLLBACK
RETURN
END
END
END
Triger ei rakendu, kui ühendutakse Dedicated Administrator Connection-i kaudu
Päring teada saamaks, kes ja kuidas sul SQL SERVER-i küljes on
SELECT s.session_id
, c.connect_time
, s.login_time
, s.login_name, s.original_login_name
, c.protocol_type
, c.client_net_address
, c.client_tcp_port
, c.auth_scheme
, s.HOST_NAME
, s.program_name, s.client_interface_name
FROM sys.dm_exec_sessions s
JOIN sys.dm_exec_connections c
ON s.session_id = c.session_id
Blogged with the Flock Browser
kolmapäev, 13. mai 2009
IIS6 ReturnUrl, automaatne edasisuunamine tuvastamiseks
Veebirakendusel on mitu sisselogimislehekülge näiteks
loginTen.aspx
loginEmp.aspx
ja tahad nagu saada logida saidile veebilehelt XXXXX\loginTen.aspx
aga brauser pöörab URL-i hoopis XXXX\loginEmp.aspx?ReturnUrl=%2floginTen.aspx
See juhtub siis, kui rakenduse Web.Config seadistada nii, et kõik audentimata kasutajad on keelatud, sel juhul IIS suuneb edasi"forms loginUrl" toodud lehe peale
<authentication mode="Forms">
<forms loginUrl="~/loginEmp.aspx" timeout="60" />
</authentication>
<authorization>
<deny users="?" />
</authorization>
asi läheb tagasi korda kui lubada rakendust joosta kõikide kontode all
<authorization>
<allow users="*"/>
<deny users="?" />
</authorization>
loginTen.aspx
loginEmp.aspx
ja tahad nagu saada logida saidile veebilehelt XXXXX\loginTen.aspx
aga brauser pöörab URL-i hoopis XXXX\loginEmp.aspx?ReturnUrl=%2floginTen.aspx
See juhtub siis, kui rakenduse Web.Config seadistada nii, et kõik audentimata kasutajad on keelatud, sel juhul IIS suuneb edasi"forms loginUrl" toodud lehe peale
<authentication mode="Forms">
<forms loginUrl="~/loginEmp.aspx" timeout="60" />
</authentication>
<authorization>
<deny users="?" />
</authorization>
asi läheb tagasi korda kui lubada rakendust joosta kõikide kontode all
<authorization>
<allow users="*"/>
<deny users="?" />
</authorization>
Blogged with the Flock Browser
reede, 8. mai 2009
XML muutuja tagastamine MS SQL SERVER-i salvestatud protseduurist
Isegi siin on omapärad, on salvestatud protseduur, kust tagastatakse ka XML tüüpi muutuja
Salvestatud protseduur ise
ALTER PROCEDURE [dbo].[HOUSE_DEP_KUIDO_U]
@teenuse_id NCHAR(5),
@genarved XML=NULL OUTPUT --seda tahame kätte saada
--siin annab @genarved muutujale väärtuse
DECLARE @arved TABLE (account_id BIGINT PRIMARY KEY)
INSERT INTO @arved (account_id) VALUES(13)
INSERT INTO @arved (account_id) VALUES(12)
SET @genarved = ( SELECT account_id AS 'Invoice/@InvoiceId' FROM @arved FOR XML PATH(''), TYPE, ROOT('Invoices') )
tulemus on SQL-is XML-ina on
<Invoices>
<Invoice InvoiceId="12" />
<Invoice InvoiceId="13" />
</Invoices>
Antud asja ADO.NET-is kasutamine
using System.Data.SqlClient;
using System.Xml;
using System.Data;
using (SqlConnection konn = new SqlConnection(Configuration.ConnectionString))
{
SqlCommand komm = new SqlCommand("[dbo].[HOUSE_DEP_KUIDO_U]", konn);
komm.CommandType = CommandType.StoredProcedure;
// siin tuleb SqlDbType.Xml tüübi suuruseks panna positiivne arv ja määrab ka et on tagastatav parameeter
komm.Parameters.Add("@genarved", SqlDbType.Xml,8).Direction = ParameterDirection.InputOutput;
konn.Open();
komm.ExecuteNonQuery();
}
//XML muutuja lugemine ADO.NET XmlDocument objekti
XmlDocument kort = new XmlDocument();
kort.LoadXml(komm.Parameters["@genarved"].Value.ToString().Trim());
Salvestatud protseduur ise
ALTER PROCEDURE [dbo].[HOUSE_DEP_KUIDO_U]
@teenuse_id NCHAR(5),
@genarved XML=NULL OUTPUT --seda tahame kätte saada
--siin annab @genarved muutujale väärtuse
DECLARE @arved TABLE (account_id BIGINT PRIMARY KEY)
INSERT INTO @arved (account_id) VALUES(13)
INSERT INTO @arved (account_id) VALUES(12)
SET @genarved = ( SELECT account_id AS 'Invoice/@InvoiceId' FROM @arved FOR XML PATH(''), TYPE, ROOT('Invoices') )
tulemus on SQL-is XML-ina on
<Invoices>
<Invoice InvoiceId="12" />
<Invoice InvoiceId="13" />
</Invoices>
Antud asja ADO.NET-is kasutamine
using System.Data.SqlClient;
using System.Xml;
using System.Data;
using (SqlConnection konn = new SqlConnection(Configuration.ConnectionString))
{
SqlCommand komm = new SqlCommand("[dbo].[HOUSE_DEP_KUIDO_U]", konn);
komm.CommandType = CommandType.StoredProcedure;
// siin tuleb SqlDbType.Xml tüübi suuruseks panna positiivne arv ja määrab ka et on tagastatav parameeter
komm.Parameters.Add("@genarved", SqlDbType.Xml,8).Direction = ParameterDirection.InputOutput;
konn.Open();
komm.ExecuteNonQuery();
}
//XML muutuja lugemine ADO.NET XmlDocument objekti
XmlDocument kort = new XmlDocument();
kort.LoadXml(komm.Parameters["@genarved"].Value.ToString().Trim());
Blogged with the Flock Browser
Javascripti alert aken UpdatePaneli sees
Kui peale mingit toimingut vaja näidata ekraanil JavaScripti kinnitusakent aga lehel kasutame UpdatePanel-it siis selle UpdatePaneli sees
JavaScript alert käib niimoodi
String scriptString ="";
string alertText = "Reaalsus on kestev illusioon";
// siin script language=""javascript"" on oluline
scriptString = @"<script language=""javascript""> alert('" + alertText + "');</script>";
if (!this.Page.ClientScript.IsClientScriptBlockRegistered("clientScript"))
{
//kuna oleme updatepaneli sees, tuleb seda ScriptManager.RegisterStartupScript meetodit kasutada
ScriptManager.RegisterStartupScript(this,this.GetType(), "clientScript", scriptString, false);
}
JavaScript alert käib niimoodi
String scriptString ="";
string alertText = "Reaalsus on kestev illusioon";
// siin script language=""javascript"" on oluline
scriptString = @"<script language=""javascript""> alert('" + alertText + "');</script>";
if (!this.Page.ClientScript.IsClientScriptBlockRegistered("clientScript"))
{
//kuna oleme updatepaneli sees, tuleb seda ScriptManager.RegisterStartupScript meetodit kasutada
ScriptManager.RegisterStartupScript(this,this.GetType(), "clientScript", scriptString, false);
}
Blogged with the Flock Browser
kolmapäev, 6. mai 2009
IE8-ga VisualStudio2008-s debugimisel "kaovad" sessioonimuutujad httpCookies requireSSL="true" puhul
kui web.config failis see rida juures
<httpCookies requireSSL="true" />
siis VisualStudio2008 ja IE8-ga debugides hakkavad sessioonimuutujad "kaduma". Lähevad erinevasse lõime või toimub pöördumine asünkroonselt. Ilmeb siis, kui veebileht pöördub mingis teises DLL-s oleva meetodi poole, mis neid sessioonimuutujaid näpib.
Debugimise ajaks kommenteeri web.configist antud rida välja
<httpCookies requireSSL="true" />
siis VisualStudio2008 ja IE8-ga debugides hakkavad sessioonimuutujad "kaduma". Lähevad erinevasse lõime või toimub pöördumine asünkroonselt. Ilmeb siis, kui veebileht pöördub mingis teises DLL-s oleva meetodi poole, mis neid sessioonimuutujaid näpib.
Debugimise ajaks kommenteeri web.configist antud rida välja
Blogged with the Flock Browser
teisipäev, 28. aprill 2009
Räsi arvutav CLR funktsioon MS SQL SERVERILE
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Security.Cryptography;
public partial class UserDefinedFunctions
{
[Microsoft.SqlServer.Server.SqlFunction]
public static byte[] ArvutaRasi(SqlString sona) //STRINGINA ANNAB teksti sisse
{
System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
byte[] data = encoding.GetBytes((string)sona); ;
byte[] result;
SHA512 shaM = new SHA512Managed(); //SHA512 või mõni muu
result = shaM.ComputeHash(data);
return result; //bitijada tagasi
}
};
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Security.Cryptography;
public partial class UserDefinedFunctions
{
[Microsoft.SqlServer.Server.SqlFunction]
public static byte[] ArvutaRasi(SqlString sona) //STRINGINA ANNAB teksti sisse
{
System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
byte[] data = encoding.GetBytes((string)sona); ;
byte[] result;
SHA512 shaM = new SHA512Managed(); //SHA512 või mõni muu
result = shaM.ComputeHash(data);
return result; //bitijada tagasi
}
};
Blogged with the Flock Browser
esmaspäev, 27. aprill 2009
Kuupäevad SQL SERVERIS
Kui vaja võtta DATETIME kuupäevast ära millisekundid
ALTER FUNCTION [dbo].[SEKUNDID_AINULT] ( @kuupaev DATETIME )
RETURNS DATETIME
AS /* Lõikab sisseantud kuupäevast maha millisekundid */
BEGIN
DECLARE @a_data DATETIME
DECLARE @c CHAR(19)
SET @c=CONVERT(CHAR(19),@kuupaev,126 ) --ISO8601 formaat
SET @a_data = CAST(@c AS DATETIME)
RETURN @a_data
END
Kui vaja ainult kuupäeva:
ALTER FUNCTION [dbo].[KUUPAEV_AINULT] ( @kuupaev DATETIME )
RETURNS DATETIME
AS /* Lõikab sisseantud kuupäevast maha tunnid, minutid, sekundid */
BEGIN
DECLARE @a_data DATETIME
DECLARE @c NCHAR(8)
SET @c=CONVERT(NCHAR(8),@kuupaev,112 )
SET @a_data = CAST(@c AS DATETIME)
RETURN @a_data
END
Mõlemad isetehtud funktsioonid töötavad väga hästi erinevate SQL SERVER-i versioonide ja seadistuste korral
ALTER FUNCTION [dbo].[SEKUNDID_AINULT] ( @kuupaev DATETIME )
RETURNS DATETIME
AS /* Lõikab sisseantud kuupäevast maha millisekundid */
BEGIN
DECLARE @a_data DATETIME
DECLARE @c CHAR(19)
SET @c=CONVERT(CHAR(19),@kuupaev,126 ) --ISO8601 formaat
SET @a_data = CAST(@c AS DATETIME)
RETURN @a_data
END
Kui vaja ainult kuupäeva:
ALTER FUNCTION [dbo].[KUUPAEV_AINULT] ( @kuupaev DATETIME )
RETURNS DATETIME
AS /* Lõikab sisseantud kuupäevast maha tunnid, minutid, sekundid */
BEGIN
DECLARE @a_data DATETIME
DECLARE @c NCHAR(8)
SET @c=CONVERT(NCHAR(8),@kuupaev,112 )
SET @a_data = CAST(@c AS DATETIME)
RETURN @a_data
END
Mõlemad isetehtud funktsioonid töötavad väga hästi erinevate SQL SERVER-i versioonide ja seadistuste korral
Blogged with the Flock Browser
neljapäev, 23. aprill 2009
XML muutujaga pakettmuudatuse (Batch Update) sooritamine
Ühekaupa SQL SERVER-is ridu muuta on SQL SERVER-ile väga piinarikas
kui vaja portsu ridadega andmebaasis midagi teha siis saab kasutada XML muutujat selle asja tegemiseks
Ekraanil mingi asp:TreeNode element, kus saab linnukesega ära märkida, et muuda nüüd selle rea andmeid
Kõigepealt teeb valmis XML muutuja, mille annab andmebaasi protseduuri sisse
using System.Xml;
XmlDocument xdoc = new XmlDocument();
XmlElement el;
el = xdoc.CreateElement("CvNodeElement"); //juurikas
xdoc.AppendChild(el);
foreach (TreeNode no in nod)
{
va = no.Value;
XmlElement childelmt;
XmlAttribute childattr;
//Create child with ID attribute
childelmt = xdoc.CreateElement("Node");
childattr = xdoc.CreateAttribute("ItemId");
childattr.Value = va.ToString();
childelmt.Attributes.Append(childattr);
childattr = xdoc.CreateAttribute("IsPublic");
childattr.Value = no.Checked ? "1" : "0";
childelmt.Attributes.Append(childattr);
el.AppendChild(childelmt);
}
SqlCommandile nüüd XML parameeter külge
komm.Parameters.Add("@doc", SqlDbType.Xml);
komm.Parameters["@doc"].Value = xdoc.InnerXml;
Andmebaasi protseduur
ALTER PROCEDURE [dbo].[CVPublish_Kuido_U]
@doc XML --xml muutuja mis tehakse asp.net-is valmis
AS
BEGIN
SET XACT_ABORT ON
SET NOCOUNT ON
DECLARE @idoc INT
DECLARE @muutused TABLE (Itemid INT, IsPublic BIT)
--lammutame XML-i tabelmuutujaks
EXEC sp_xml_preparedocument @idoc OUTPUT, @doc
INSERT INTO @muutused ([Itemid],[IsPublic])
SELECT Itemid , IsPublic
FROM OPENXML (@idoc, '/CvNodeElement/Node',1)
WITH (ItemId INT, IsPublic BIT)
EXEC sp_xml_removedocument @idoc
--ja nüüd muudame andmebaasis portsul kirjetel
-- CV_CfPersResPatId on tabeli primaarvõti
UPDATE dbo.[CV_CfPersResPat]
SET [CV_CfPersResPat].[IsPublic] = ec.[IsPublic]
FROM dbo.[CV_CfPersResPat] INNER JOIN @muutused AS ec
ON ( CV_CfPersResPat.CV_CfPersResPatId = ec.Itemid
AND [CV_CfPersResPat].[IsPublic] <> ec.[IsPublic] --muudame ainult neil, milel on IsPublic muutunud, hoiab veelgi kokku
)
END
XML-iga muutujate sisseandmist saab kasutada ka siis, kui on vaja protseduurile korraga palju parameetreid sisse annda
kui vaja portsu ridadega andmebaasis midagi teha siis saab kasutada XML muutujat selle asja tegemiseks
Ekraanil mingi asp:TreeNode element, kus saab linnukesega ära märkida, et muuda nüüd selle rea andmeid
Kõigepealt teeb valmis XML muutuja, mille annab andmebaasi protseduuri sisse
using System.Xml;
XmlDocument xdoc = new XmlDocument();
XmlElement el;
el = xdoc.CreateElement("CvNodeElement"); //juurikas
xdoc.AppendChild(el);
foreach (TreeNode no in nod)
{
va = no.Value;
XmlElement childelmt;
XmlAttribute childattr;
//Create child with ID attribute
childelmt = xdoc.CreateElement("Node");
childattr = xdoc.CreateAttribute("ItemId");
childattr.Value = va.ToString();
childelmt.Attributes.Append(childattr);
childattr = xdoc.CreateAttribute("IsPublic");
childattr.Value = no.Checked ? "1" : "0";
childelmt.Attributes.Append(childattr);
el.AppendChild(childelmt);
}
SqlCommandile nüüd XML parameeter külge
komm.Parameters.Add("@doc", SqlDbType.Xml);
komm.Parameters["@doc"].Value = xdoc.InnerXml;
Andmebaasi protseduur
ALTER PROCEDURE [dbo].[CVPublish_Kuido_U]
@doc XML --xml muutuja mis tehakse asp.net-is valmis
AS
BEGIN
SET XACT_ABORT ON
SET NOCOUNT ON
DECLARE @idoc INT
DECLARE @muutused TABLE (Itemid INT, IsPublic BIT)
--lammutame XML-i tabelmuutujaks
EXEC sp_xml_preparedocument @idoc OUTPUT, @doc
INSERT INTO @muutused ([Itemid],[IsPublic])
SELECT Itemid , IsPublic
FROM OPENXML (@idoc, '/CvNodeElement/Node',1)
WITH (ItemId INT, IsPublic BIT)
EXEC sp_xml_removedocument @idoc
--ja nüüd muudame andmebaasis portsul kirjetel
-- CV_CfPersResPatId on tabeli primaarvõti
UPDATE dbo.[CV_CfPersResPat]
SET [CV_CfPersResPat].[IsPublic] = ec.[IsPublic]
FROM dbo.[CV_CfPersResPat] INNER JOIN @muutused AS ec
ON ( CV_CfPersResPat.CV_CfPersResPatId = ec.Itemid
AND [CV_CfPersResPat].[IsPublic] <> ec.[IsPublic] --muudame ainult neil, milel on IsPublic muutunud, hoiab veelgi kokku
)
END
XML-iga muutujate sisseandmist saab kasutada ka siis, kui on vaja protseduurile korraga palju parameetreid sisse annda
Blogged with the Flock Browser
esmaspäev, 20. aprill 2009
Kirjutame ja loeme Windows Serveri Application logisse kasutades LINQ-i
Aeg-ajlat ika viskab vigu ja mõtekas need veateated kuskilegi kirja panna, et hiljem saaks uurida mis süsteemis tegelikult juhtus. Täiesti võimalik on kasutada selleks Windows Serveri EventLog-i
Kõigepealt teeb eelnevalt käsitsi ühe vastava võtme REGEDIT-iga Windows Serverisse
HKEY_LOCAL_MACHINE -> System -> CurrentControlSet -> Services -> EventLog -> Application ja seal paremklõps hiirega Add New Key ja lisab uue võtme MINURAKENDUS
Kui kasutada rakenduse enda vaikimisi veahaldust, ehk Web.Config-is on sees
customErrors mode="RemoteOnly" defaultRedirect="KampError.aspx" redirectMode="ResponseRewrite"
// redirectMode="ResponseRewrite" on .NET Framework 3.5 uuendus
siis KampError.aspx Page_Load meetod võiks välja näha selline
protected void Page_Load(object sender, EventArgs e)
{
this.LiteralViga.Text = "Süsteemis juhtus järgmine tõrge: ";
try
{
Exception ex = Server.GetLastError().GetBaseException();
if (ex != null)
{
this.LiteralViga.Text += "
" + ex.Message.Trim();
// vealogisse kirjutamisel ja ekraanile näitamisel tuleb muidugi jälgida turvalisuse nõudeid
string viga = "SOURCE: " + (ex.Source ?? "") +
"URL: " + (Request.Url == null ? "" : Request.Url.ToString()) +
"URLREFERRER: " + (Request.UrlReferrer == null ? "" : Request.UrlReferrer.ToString()) +
"Crawler: " + (Request.Browser.Crawler == null ? "" : Request.Browser.Crawler.ToString()) +
"USERHOSTNAME: " + (Request.UserHostName == null ? "" : Request.UserHostName.ToString()) +
"USERHOSTADDRESS: " + (Request.UserHostAddress == null ? "" : Request.UserHostAddress.ToString()) +
"USERAGENT: " + (Request.UserAgent == null ? "" : Request.UserAgent.ToString()) +
"QUERYSTRING: " + (Request.QueryString == null ? "" : Request.QueryString.ToString());
//näitame midagi ka ekraanile
this.LabelViga.Text = viga;
if (EventLog.SourceExists("MINURAKENDUS", ".")) //kontrollib, kas on see võti olemas jooksval serveril
{
//logisse kirjutab rohkem võrreldes ekraanile näitamisega
viga += "/nTARGETSITE: " + (ex.TargetSite == null ? "" : ex.TargetSite.ToString()) +
"/nSTACKTRACE: " + (ex.StackTrace == null ? "" : ex.StackTrace) +
"/nINNEREXEPTION: " + (ex.InnerException == null ? "" : ex.InnerException.ToString());
//kirjutame logisse
EventLog.WriteEntry("MINURAKENDUS", this.LiteralViga.Text + "\n" + viga.Replace("
", "\n"), EventLogEntryType.Error);
}
Server.ClearError();
}
}
catch (SystemException ex)
{
this.LabelViga.Text = ex.Message;
}
}
ja kui nüüd vaja lugeda seda MINURAKENDUS vealogi
if (EventLog.SourceExists("MINURAKENDUS"))
{
//siin saab teada selle logi nime, kuhu sisse kirjutame, tavaliselt Application Log
this.literalErrSource.Text = EventLog.LogNameFromSourceName("MINURAKENDUS", ".");
EventLog[] logid = EventLog.GetEventLogs("."); //jooksva serveri vealogid
EventLog kalog = null;
//otsime nime järgi ülesse selle logi nime, kuhu oma veateated sisse kirjutame
foreach (EventLog elog in logid)
{
if (elog.Log == this.literalErrSource.Text)
{
kalog = elog; //leitud
break;
}
}
if (kalog != null) //kui leidsime logi nime
{
//otsime välja MINURAKENDUS teated ja vead
// üks koht kus on mõistlik kasutada LINQ-i
var query = from EventLogEntry el in kalog.Entries
where el.Source == "MINURAKENDUS"
orderby el.TimeGenerated descending
select new
{
Time = el.TimeGenerated,
Message = el.Message,
// Category = el.Category,
EntryType = el.EntryType.ToString(),
// TimeWritten = el.TimeWritten,
UserName = el.UserName
};
//bindime GridView külge ekraanile näitamiseks
this.GridViewLogid.DataSource = query.ToList();
this.GridViewLogid.DataBind();
}
else //kui ei leidnud seda logi nime, kuhu enda veateated kirja paneme näitame lihtsalt logide nimetusi
{
this.GridViewLogid.DataSource = logid;
this.GridViewLogid.DataBind();
}
}
ja edaspidi ei pea enam tõrgete uurimiseks serverisse sisse logima vaid saad vaadata otse rakenduse enda kaudu.
Kõigepealt teeb eelnevalt käsitsi ühe vastava võtme REGEDIT-iga Windows Serverisse
HKEY_LOCAL_MACHINE -> System -> CurrentControlSet -> Services -> EventLog -> Application ja seal paremklõps hiirega Add New Key ja lisab uue võtme MINURAKENDUS
Kui kasutada rakenduse enda vaikimisi veahaldust, ehk Web.Config-is on sees
customErrors mode="RemoteOnly" defaultRedirect="KampError.aspx" redirectMode="ResponseRewrite"
// redirectMode="ResponseRewrite" on .NET Framework 3.5 uuendus
siis KampError.aspx Page_Load meetod võiks välja näha selline
protected void Page_Load(object sender, EventArgs e)
{
this.LiteralViga.Text = "Süsteemis juhtus järgmine tõrge: ";
try
{
Exception ex = Server.GetLastError().GetBaseException();
if (ex != null)
{
this.LiteralViga.Text += "
" + ex.Message.Trim();
// vealogisse kirjutamisel ja ekraanile näitamisel tuleb muidugi jälgida turvalisuse nõudeid
string viga = "SOURCE: " + (ex.Source ?? "") +
"URL: " + (Request.Url == null ? "" : Request.Url.ToString()) +
"URLREFERRER: " + (Request.UrlReferrer == null ? "" : Request.UrlReferrer.ToString()) +
"Crawler: " + (Request.Browser.Crawler == null ? "" : Request.Browser.Crawler.ToString()) +
"USERHOSTNAME: " + (Request.UserHostName == null ? "" : Request.UserHostName.ToString()) +
"USERHOSTADDRESS: " + (Request.UserHostAddress == null ? "" : Request.UserHostAddress.ToString()) +
"USERAGENT: " + (Request.UserAgent == null ? "" : Request.UserAgent.ToString()) +
"QUERYSTRING: " + (Request.QueryString == null ? "" : Request.QueryString.ToString());
//näitame midagi ka ekraanile
this.LabelViga.Text = viga;
if (EventLog.SourceExists("MINURAKENDUS", ".")) //kontrollib, kas on see võti olemas jooksval serveril
{
//logisse kirjutab rohkem võrreldes ekraanile näitamisega
viga += "/nTARGETSITE: " + (ex.TargetSite == null ? "" : ex.TargetSite.ToString()) +
"/nSTACKTRACE: " + (ex.StackTrace == null ? "" : ex.StackTrace) +
"/nINNEREXEPTION: " + (ex.InnerException == null ? "" : ex.InnerException.ToString());
//kirjutame logisse
EventLog.WriteEntry("MINURAKENDUS", this.LiteralViga.Text + "\n" + viga.Replace("
", "\n"), EventLogEntryType.Error);
}
Server.ClearError();
}
}
catch (SystemException ex)
{
this.LabelViga.Text = ex.Message;
}
}
ja kui nüüd vaja lugeda seda MINURAKENDUS vealogi
if (EventLog.SourceExists("MINURAKENDUS"))
{
//siin saab teada selle logi nime, kuhu sisse kirjutame, tavaliselt Application Log
this.literalErrSource.Text = EventLog.LogNameFromSourceName("MINURAKENDUS", ".");
EventLog[] logid = EventLog.GetEventLogs("."); //jooksva serveri vealogid
EventLog kalog = null;
//otsime nime järgi ülesse selle logi nime, kuhu oma veateated sisse kirjutame
foreach (EventLog elog in logid)
{
if (elog.Log == this.literalErrSource.Text)
{
kalog = elog; //leitud
break;
}
}
if (kalog != null) //kui leidsime logi nime
{
//otsime välja MINURAKENDUS teated ja vead
// üks koht kus on mõistlik kasutada LINQ-i
var query = from EventLogEntry el in kalog.Entries
where el.Source == "MINURAKENDUS"
orderby el.TimeGenerated descending
select new
{
Time = el.TimeGenerated,
Message = el.Message,
// Category = el.Category,
EntryType = el.EntryType.ToString(),
// TimeWritten = el.TimeWritten,
UserName = el.UserName
};
//bindime GridView külge ekraanile näitamiseks
this.GridViewLogid.DataSource = query.ToList();
this.GridViewLogid.DataBind();
}
else //kui ei leidnud seda logi nime, kuhu enda veateated kirja paneme näitame lihtsalt logide nimetusi
{
this.GridViewLogid.DataSource = logid;
this.GridViewLogid.DataBind();
}
}
ja edaspidi ei pea enam tõrgete uurimiseks serverisse sisse logima vaid saad vaadata otse rakenduse enda kaudu.
SQL SERVER Agent kuupäeva funktsioon
Kui lugeda andmeid SQL SERVER Agent tabelitest, MSDB andmebaasist siis kuupäeva ja kellaaeg on antud seal INT väärtuste kujul, et nüüd nendest asjadest mõistlikku kuupäeva saada võib kasutada järgmist funktsiooni mis genereerib kellaaja lähtudes tabeli date ja time numbritest
CREATE FUNCTION [dbo].[SQLSERVERAGENTDATETIME_KUIDO] (@agentdate INT, @agenttime INT)
RETURNS DATETIME
AS
BEGIN
DECLARE @Result DATETIME
DECLARE @date DATETIME, @year INT, @month INT, @day INT, @datestr NVARCHAR(40)
,@hour INT, @min INT, @sec INT, @timestr NVARCHAR(40)
SET @year = (@agentdate / 10000)
SET @month = (@agentdate - (@year * 10000)) / 100
SET @day = (@agentdate - (@year * 10000) - (@month * 100))
IF @agentdate = 0
RETURN @Result --võib rõõmsalt ka NULL-i tagasi anda, kui kuupäeva pole
SET @datestr = CONVERT(NVARCHAR(4), @year) +
RIGHT('0'+CONVERT(NVARCHAR(2), @month),2) +
RIGHT('0'+CONVERT(NVARCHAR(2), @day),2)
SET @hour = (@agenttime / 10000)
SET @min = (@agenttime - (@hour * 10000)) / 100
SET @sec = (@agenttime - (@hour * 10000) - (@min * 100))
SET @timestr = RIGHT('00'+CONVERT(NVARCHAR(2), @hour),2) + N':' +
RIGHT('00'+CONVERT(NVARCHAR(2), @min),2) + N':' +
RIGHT('00'+CONVERT(NVARCHAR(2), @sec),2)
SET @Result = CONVERT(DATETIME, @datestr+' '+@timestr,112)
RETURN @Result
END
Kasutada niimoodi, kui vaja teada millal automaatseid töid käivitati
SELECT [message], run_status, sql_severity, step_id
,[dbo].[SQLSERVERAGENTDATETIME_KUIDO](run_date, run_time) AS RUN_TIME FROM MSDB.dbo.sysjobhistory
CREATE FUNCTION [dbo].[SQLSERVERAGENTDATETIME_KUIDO] (@agentdate INT, @agenttime INT)
RETURNS DATETIME
AS
BEGIN
DECLARE @Result DATETIME
DECLARE @date DATETIME, @year INT, @month INT, @day INT, @datestr NVARCHAR(40)
,@hour INT, @min INT, @sec INT, @timestr NVARCHAR(40)
SET @year = (@agentdate / 10000)
SET @month = (@agentdate - (@year * 10000)) / 100
SET @day = (@agentdate - (@year * 10000) - (@month * 100))
IF @agentdate = 0
RETURN @Result --võib rõõmsalt ka NULL-i tagasi anda, kui kuupäeva pole
SET @datestr = CONVERT(NVARCHAR(4), @year) +
RIGHT('0'+CONVERT(NVARCHAR(2), @month),2) +
RIGHT('0'+CONVERT(NVARCHAR(2), @day),2)
SET @hour = (@agenttime / 10000)
SET @min = (@agenttime - (@hour * 10000)) / 100
SET @sec = (@agenttime - (@hour * 10000) - (@min * 100))
SET @timestr = RIGHT('00'+CONVERT(NVARCHAR(2), @hour),2) + N':' +
RIGHT('00'+CONVERT(NVARCHAR(2), @min),2) + N':' +
RIGHT('00'+CONVERT(NVARCHAR(2), @sec),2)
SET @Result = CONVERT(DATETIME, @datestr+' '+@timestr,112)
RETURN @Result
END
Kasutada niimoodi, kui vaja teada millal automaatseid töid käivitati
SELECT [message], run_status, sql_severity, step_id
,[dbo].[SQLSERVERAGENTDATETIME_KUIDO](run_date, run_time) AS RUN_TIME FROM MSDB.dbo.sysjobhistory
Veebilehe laadimisaja suurendamine
Kui juhtub nii, et veebilehe tegemiseks kulub tavalisest rohkem aega ja pillub lõpuks veateadet
System.Web.HttpException Request timed out
Sel juhul kui miski muu enam ei aita tuleb seda veebilehe tegemise aega suuendada
Server.ScriptTimeout = 600; // sätib aja 5 minuti peale
System.Web.HttpException Request timed out
Sel juhul kui miski muu enam ei aita tuleb seda veebilehe tegemise aega suuendada
Server.ScriptTimeout = 600; // sätib aja 5 minuti peale
Blogged with the Flock Browser
neljapäev, 16. aprill 2009
System.Net.Mail MailMessage.BodyEncoding läheb hieroglüüfe täis
Saadad ülalminitud asjaga e-posti ja kui võtad Outlookiga kirja lahti ja Vasta tuleb pilt selline
asja saab kord kui Unicode kodeering asendada ANSI 1252-ga
//email.BodyEncoding = Encoding.Unicode; //see paneb Outlooki hieroglüüfid sisse
email.BodyEncoding = System.Text.Encoding.GetEncoding(1252);
email.IsBodyHtml = false;
asja saab kord kui Unicode kodeering asendada ANSI 1252-ga
//email.BodyEncoding = Encoding.Unicode; //see paneb Outlooki hieroglüüfid sisse
email.BodyEncoding = System.Text.Encoding.GetEncoding(1252);
email.IsBodyHtml = false;
Blogged with the Flock Browser
teisipäev, 7. aprill 2009
SQLConnectionPooli tühjendamine
Juhul, näiteks, kui muudame SQL SERVER Logini parameetreid, näiteks Default Language siis võib juhtuda, et saame veateate
Resetting the connection results in a different state than the initial login. The login fails. Login failed for user 'MINE_KUULE'. A severe error occurred on the current command. The results, if any, should be discarded.
Põhjuseks on SQL Connection Pooli(basseini) olemasolu, mis peab meeles mis sätetega SQL SERVERI login basseini tuli ja kui vahepeal loginit muuta siis basseinis jääb see ju uuendamata. Kui nüüd teha uus päring andmebaasi siis Connection Pooli ja SQLSERVERI login ei lange enam parameetrite poolest kokku.
Lahti saab asjast nii, et tuleb bassein peale SQL SERVER logini muutmist tühjendada
Näiteks muudame SQL SERVER logini keelt süsteemse protseduuriga
EXECUTE sp_defaultlanguage @loginame = @login_name , @language = @lang_name
siis tema kasutamine koos pooli tühjendmisega näeb välja nii, ( DBO.SET_WORKER_LANGUAGE_KUIDO_U on üks enda tehtud salvestatud protseduur mille
sees ka seda sp_defaultlanguage kasutatakse)
using System.Data;
using System.Data.SqlClient;
using (SqlConnection Connection = new SqlConnection(Configuration.ConnectionString))
{
SqlCommand Command = new SqlCommand("DBO.SET_WORKER_LANGUAGE_KUIDO_U",Connection);
Command.CommandType=CommandType.StoredProcedure;
Command.Parameters.AddWithValue("@login_name", username.Trim());
Command.Parameters.AddWithValue("@lang_name", language.Trim());
Connection.Open();
Command.ExecuteNonQuery();
Connection.Close();
//basseini tühjendamine ainult selle ühenduse logini jaoks
SqlConnection.ClearPool(Connection);
// SqlConnection.ClearAllPools(); //kogu bassein tühjaks
}
Resetting the connection results in a different state than the initial login. The login fails. Login failed for user 'MINE_KUULE'. A severe error occurred on the current command. The results, if any, should be discarded.
Põhjuseks on SQL Connection Pooli(basseini) olemasolu, mis peab meeles mis sätetega SQL SERVERI login basseini tuli ja kui vahepeal loginit muuta siis basseinis jääb see ju uuendamata. Kui nüüd teha uus päring andmebaasi siis Connection Pooli ja SQLSERVERI login ei lange enam parameetrite poolest kokku.
Lahti saab asjast nii, et tuleb bassein peale SQL SERVER logini muutmist tühjendada
Näiteks muudame SQL SERVER logini keelt süsteemse protseduuriga
EXECUTE sp_defaultlanguage @loginame = @login_name , @language = @lang_name
siis tema kasutamine koos pooli tühjendmisega näeb välja nii, ( DBO.SET_WORKER_LANGUAGE_KUIDO_U on üks enda tehtud salvestatud protseduur mille
sees ka seda sp_defaultlanguage kasutatakse)
using System.Data;
using System.Data.SqlClient;
using (SqlConnection Connection = new SqlConnection(Configuration.ConnectionString))
{
SqlCommand Command = new SqlCommand("DBO.SET_WORKER_LANGUAGE_KUIDO_U",Connection);
Command.CommandType=CommandType.StoredProcedure;
Command.Parameters.AddWithValue("@login_name", username.Trim());
Command.Parameters.AddWithValue("@lang_name", language.Trim());
Connection.Open();
Command.ExecuteNonQuery();
Connection.Close();
//basseini tühjendamine ainult selle ühenduse logini jaoks
SqlConnection.ClearPool(Connection);
// SqlConnection.ClearAllPools(); //kogu bassein tühjaks
}
Blogged with
the Flock Browser
the Flock Browser
neljapäev, 26. märts 2009
ASP.NET ReportViewer Controli kasutamine koos IE8-ga
IE8 on väljas ja kui on ASP.NET-is kasutusel ReportViewer Contol siis tekib sinna ka printeri ikoon
kui nüüd tahta seda välja trükkida, võib ilmuda IE8 ActiveX paigaldamise hoiatusteade ja kui see paigaldamine ära teha ja siis uuesti trükkida proovida võib ilmuda veateade "Unable to load client print protocol".
Selle asja saab sisevõrgus korda IE8 sätete seadmisega:
Edasi
sätime veebilehe
lubatud sisevõrgu turvalisse tsooni
kui nüüd tahta seda välja trükkida, võib ilmuda IE8 ActiveX paigaldamise hoiatusteade ja kui see paigaldamine ära teha ja siis uuesti trükkida proovida võib ilmuda veateade "Unable to load client print protocol".
Selle asja saab sisevõrgus korda IE8 sätete seadmisega:
Edasi
sätime veebilehe
lubatud sisevõrgu turvalisse tsooni
CustomValidator args.IsValid = false; ja ei mitte kui midagi muud
Et mitte korduvalt sama reha peale astuda siis puust ja punaselt, et kui kasutad veebilehe peal CustomValidatorit
siis tema ServerValidate eventis tuleb väära asja teada andmiseks kasutada args.IsValid = false;
protected void CustomValidatorSolver_ServerValidate(object source, ServerValidateEventArgs args)
{
if (this.DropDownListTeostaja.SelectedValue == "-1")
{
this.CustomValidatorSolver.ErrorMessage = "Räige reeglite rikkumine";
args.IsValid = false;
}
}
sellest ei ole kasu kui kasutad
this.CustomValidatorSolver.IsValid = false;
niipea kui tuled ServerValidate meetodist välja pöörab ASP.NET CustomValidatorSolver.IsValid tagasi true peale
P.S. Mõnikord on üldse kasulikum vähem programmeerida, kui mingi asi välja ei tule, mine töölt minema ja tule
järgmine päev tagasi. Võidad pool päeva asjatut närvitsemist.
siis tema ServerValidate eventis tuleb väära asja teada andmiseks kasutada args.IsValid = false;
protected void CustomValidatorSolver_ServerValidate(object source, ServerValidateEventArgs args)
{
if (this.DropDownListTeostaja.SelectedValue == "-1")
{
this.CustomValidatorSolver.ErrorMessage = "Räige reeglite rikkumine";
args.IsValid = false;
}
}
sellest ei ole kasu kui kasutad
this.CustomValidatorSolver.IsValid = false;
niipea kui tuled ServerValidate meetodist välja pöörab ASP.NET CustomValidatorSolver.IsValid tagasi true peale
P.S. Mõnikord on üldse kasulikum vähem programmeerida, kui mingi asi välja ei tule, mine töölt minema ja tule
järgmine päev tagasi. Võidad pool päeva asjatut närvitsemist.
Blogged with the Flock Browser
teisipäev, 24. märts 2009
Kasutaja andmebaasi rollide leidmine
Vaja teada, kas andmebaasi kasutaja on mingis andmebaasi rollis. Kätte saab alloleva funktsiooniga.
SELECT [dbo].[IS_WORKER_ROLE_KUIDO_S]('AKE', 'KAMPUS_WORKER')
Mida tähele panna on see, et SQL2005/2008 ei kobise midagi selle kohta, kui kasutajal pole õigusi süsteemsete tabelite teatud ridade lugemiseks. Libisetakse lihtsalt üle ja mingit infot ei pritsita.
Kui kasutajal ULLE-l pole andmebaasis DBO õigusi aga tahab teada, kas AKE on mingis rollis siis ULLE-na sees olles päring SELECT usu.name FROM sysusers usu jätab osad read "vahele". Lahenduseks siin impersoneerimise kasutamine, ehk teeb funktsiooni WITH EXECUTE AS 'DBO' suvandiga, et korrektesid tulemusi saada
ALTER FUNCTION [dbo].[IS_WORKER_ROLE_KUIDO_S](@kasutaja NVARCHAR(25), @roll NVARCHAR(25))
RETURNS INT
WITH EXECUTE AS 'DBO' --Et oleks ligipääsu õigus kõikidele tabeli ridadele
AS
BEGIN
DECLARE @out INT
IF EXISTS( SELECT usu.name FROM
sysusers usu WITH(NOLOCK) LEFT OUTER JOIN
(sysmembers mem WITH(NOLOCK) INNER JOIN sysusers usg WITH (NOLOCK) ON mem.groupuid = usg.uid) on usu.uid = mem.memberuid
LEFT OUTER JOIN master.dbo.syslogins lo WITH (NOLOCK) ON usu.sid = lo.sid
WHERE (usu.islogin = 1 AND usu.isaliased = 0 AND usu.hasdbaccess = 1) AND
(usg.issqlrole = 1 OR usg.uid is null) AND
usu.name = @kasutaja AND usg.name=@roll )
SET @out=1
RETURN ISNULL(@out,0)
END
Blogged with the Flock Browser
Andmetäite vältimise pealepeanemine Vista peal ehk DEP
Andmetäite vältimine ehk DEP on lühidalt lahti seletatud siin
http://windowshelp.microsoft.com/Windows/et-EE/help/186de3d0-01af-4d4c-981d-674637d2f4bf1061.mspx
ja sügavamalt siin
http://support.microsoft.com/kb/875352
Kuidas seda maha ja peale panna on kirjeldatud
http://windowshelp.microsoft.com/Windows/en-US/help/1d9bb9b4-f6ba-466d-ac2b-7b8c4f8361611033.mspx
Kui on eestikeelne Vista siis piltlikult käib pealepanek nii, et avad juhtpaneeli
sealt edasi valid Süsteem
klikid Täpsustatud süsteemisätted
ja sealt vaatab Täpsemalt Jõudluse sätteid
ja lülitame DEP-i sisse
DEP hea asi selleks, et viirused nii kergesti ligi ei pääseks.
http://windowshelp.microsoft.com/Windows/et-EE/help/186de3d0-01af-4d4c-981d-674637d2f4bf1061.mspx
ja sügavamalt siin
http://support.microsoft.com/kb/875352
Kuidas seda maha ja peale panna on kirjeldatud
http://windowshelp.microsoft.com/Windows/en-US/help/1d9bb9b4-f6ba-466d-ac2b-7b8c4f8361611033.mspx
Kui on eestikeelne Vista siis piltlikult käib pealepanek nii, et avad juhtpaneeli
sealt edasi valid Süsteem
klikid Täpsustatud süsteemisätted
ja sealt vaatab Täpsemalt Jõudluse sätteid
ja lülitame DEP-i sisse
DEP hea asi selleks, et viirused nii kergesti ligi ei pääseks.
pühapäev, 22. märts 2009
ASP.NET CollapsiblePanelExtender
Kõigepealt tuleb ASPX lehe peal muuta DOCTYPE ära
<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" >
Vaja selleks, et IE asjast aru saaks, muud(Flock, Safari, Opera, Firefox) töötavad ka
standardse
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
määranguga aga IE tahab XHTML-i (on siis tegu hullumeelsuse või geniaalsusega ?)
Extenderiga seotud asp:Panel-i kokkupaneminke käib "ClientState" sättimisega
this.PanelUusprobleem_CollapsiblePanelExtender.ClientState = "true";
paneb laiendusega seotud paneeli kokku
<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" >
Vaja selleks, et IE asjast aru saaks, muud(Flock, Safari, Opera, Firefox) töötavad ka
standardse
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
määranguga aga IE tahab XHTML-i (on siis tegu hullumeelsuse või geniaalsusega ?)
Extenderiga seotud asp:Panel-i kokkupaneminke käib "ClientState" sättimisega
this.PanelUusprobleem_CollapsiblePanelExtender.ClientState = "true";
paneb laiendusega seotud paneeli kokku
Blogged with the Flock Browser
kolmapäev, 18. märts 2009
Veebilehe validaatorite grupi seadmine
Vaja näiteks, et kõik usercontroli validaatorid oleksid samas grupis
public void seaValidaatorGrupp(string vgrupp)
{
foreach (BaseValidator vali in this.Page.Validators)
{
vali.ValidationGroup = vgrupp;
}
}
public void seaValidaatorGrupp(string vgrupp)
{
foreach (BaseValidator vali in this.Page.Validators)
{
vali.ValidationGroup = vgrupp;
}
}
Blogged with the Flock Browser
neljapäev, 5. märts 2009
SQL SERVER 2005 süsadminnid ja CONTROL SERVER rollis olevad loginid
Algallikas:
http://www.sqlservercentral.com/blogs/brian_kelley/archive/2009/02/24/detecting-when-a-login-has-implicit-access-to-a-database.aspx
SELECT sp1.[name] [Login], 'sysadmin role' [Method]
FROM sys.server_principals sp1
JOIN sys.server_role_members srm
ON sp1.principal_id = srm.member_principal_id
JOIN sys.server_principals sp2
ON srm.role_principal_id = sp2.principal_id
WHERE sp2.NAME = 'sysadmin'
UNION ALL
SELECT sp3.[name], 'CONTROL SERVER'
FROM sys.server_principals sp3
JOIN sys.server_permissions perm
ON sp3.principal_id = perm.grantee_principal_id
WHERE perm.class = 100
AND perm.[type] = 'CL'
AND state = 'G'
ORDER BY [Login], [Method];
http://www.sqlservercentral.com/blogs/brian_kelley/archive/2009/02/24/detecting-when-a-login-has-implicit-access-to-a-database.aspx
SELECT sp1.[name] [Login], 'sysadmin role' [Method]
FROM sys.server_principals sp1
JOIN sys.server_role_members srm
ON sp1.principal_id = srm.member_principal_id
JOIN sys.server_principals sp2
ON srm.role_principal_id = sp2.principal_id
WHERE sp2.NAME = 'sysadmin'
UNION ALL
SELECT sp3.[name], 'CONTROL SERVER'
FROM sys.server_principals sp3
JOIN sys.server_permissions perm
ON sp3.principal_id = perm.grantee_principal_id
WHERE perm.class = 100
AND perm.[type] = 'CL'
AND state = 'G'
ORDER BY [Login], [Method];
Blogged with the Flock Browser
kolmapäev, 4. märts 2009
ASP.NET web.config faili krüptimine
Käima ajamiseks tuli päev otsa guugeldada. Tänud lõpuks nendele meestele
http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/88b15d6b-9baa-4f4d-8942-137185bfdf56/
ASP.NET-i Veebirakendusel või WebServicel vaja turvalisuse tõstmiseks ConnectionStrings osa ära krüptida
Käima sain sellise asjaga, kasutame RSA-d
1. Loome Machine level eksporditava RSA key containeri
aspnet_regiis on programm mille leiab serveril tavaliselt C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727 kataloogist
aspnet_regiis -pc "KampusKey" -exp
KampusKey on nüüd selle RSA võtme konteineri nimi, mis pannakse serveri kataloogi
C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys
edasi tuleb vaadata mis konto all sul see veebirakendus/veebiteenus töötab
Teed eraldi ASPX lehe, kust selle teada saad
this.LabelIdentity.Text = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
või vaatad IIS-i manageri alt, mis basseinis sul rakendus ujub (Application Pool)
ja annab sellele kontole (tavaliselt NT AUTHORITY\NETWORK SERVICE) RSA võtme konteinerile ligipääsu õiguse
aspnet_regiis -pa "KampusKey" "NT AUTHORITY\NETWORK SERVICE"
Peab mainima, et NETWORK SERVICE on turvalisuse koha pealt üsna hea konto veebirakenduste jooksutamiseks, veelgi parem oleks kohe endale selgeks teha
kuidas luua veebirakenduse jaoks omaette väheste õigustega konto
http://msdn.microsoft.com/en-us/library/ms998297.aspx
rakenduse web.config failis tuleb nüüd lisada rida
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0" >
<configSections>
</configSections>
<configProtectedData defaultProvider="RsaProtectedConfigurationProvider" >
<providers>
<add name="KampusVoti" type="System.Configuration.RsaProtectedConfigurationProvider, System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" keyContainerName="KampusKey" useMachineContainer="true" />
</providers>
</configProtectedData>
<connectionStrings>
<add name="TurukampusConnectionString" connectionString="Data Source=SQLBAAS;Initial Catalog=KAMPUS;User ID=KAMPUS868;Password=HKSDF6834" providerName="System.Data.SqlClient"/>
</connectionStrings>
</configuration>
ja nüüd krüptib selle connectionStrings osa ära
aspnet_regiis –pef "connectionStrings“ “d:\cw-turukampus_webservice” –prov “KampusVoti”
d:\cw-turukampus_webservice on see kataloog serveril ,kus sul rakenduse failid on ja
–prov “KampusVoti” peab kokku lengema web.config failis configProtectedData lisatud provider nimega, see sunnik oli juhendis mainimata
muidu ei tööta saad veateate
Parser Error Message: Failed to decrypt using provider 'RsaProtectedConfigurationProvider'. Error message from the provider: The RSA key container could not be opened.
Rakenduses töötab asi ühtemoodi, IIS ise krüptib/dekrüptib connectrionStrings osa lahti
using System.Web.Configuration;
System.Configuration.ConnectionStringsSection konnc = WebConfigurationManager.GetSection("connectionStrings") as System.Configuration.ConnectionStringsSection;
this.Label1.Text = konnc.ConnectionStrings["TurukampusConnectionString"].ConnectionString.Trim();
http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/88b15d6b-9baa-4f4d-8942-137185bfdf56/
ASP.NET-i Veebirakendusel või WebServicel vaja turvalisuse tõstmiseks ConnectionStrings osa ära krüptida
Käima sain sellise asjaga, kasutame RSA-d
1. Loome Machine level eksporditava RSA key containeri
aspnet_regiis on programm mille leiab serveril tavaliselt C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727 kataloogist
aspnet_regiis -pc "KampusKey" -exp
KampusKey on nüüd selle RSA võtme konteineri nimi, mis pannakse serveri kataloogi
C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys
edasi tuleb vaadata mis konto all sul see veebirakendus/veebiteenus töötab
Teed eraldi ASPX lehe, kust selle teada saad
this.LabelIdentity.Text = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
või vaatad IIS-i manageri alt, mis basseinis sul rakendus ujub (Application Pool)
ja annab sellele kontole (tavaliselt NT AUTHORITY\NETWORK SERVICE) RSA võtme konteinerile ligipääsu õiguse
aspnet_regiis -pa "KampusKey" "NT AUTHORITY\NETWORK SERVICE"
Peab mainima, et NETWORK SERVICE on turvalisuse koha pealt üsna hea konto veebirakenduste jooksutamiseks, veelgi parem oleks kohe endale selgeks teha
kuidas luua veebirakenduse jaoks omaette väheste õigustega konto
http://msdn.microsoft.com/en-us/library/ms998297.aspx
rakenduse web.config failis tuleb nüüd lisada rida
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0" >
<configSections>
</configSections>
<configProtectedData defaultProvider="RsaProtectedConfigurationProvider" >
<providers>
<add name="KampusVoti" type="System.Configuration.RsaProtectedConfigurationProvider, System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" keyContainerName="KampusKey" useMachineContainer="true" />
</providers>
</configProtectedData>
<connectionStrings>
<add name="TurukampusConnectionString" connectionString="Data Source=SQLBAAS;Initial Catalog=KAMPUS;User ID=KAMPUS868;Password=HKSDF6834" providerName="System.Data.SqlClient"/>
</connectionStrings>
</configuration>
aspnet_regiis –pef "connectionStrings“ “d:\cw-turukampus_webservice” –prov “KampusVoti”
d:\cw-turukampus_webservice on see kataloog serveril ,kus sul rakenduse failid on ja
–prov “KampusVoti” peab kokku lengema web.config failis configProtectedData lisatud provider nimega, see sunnik oli juhendis mainimata
muidu ei tööta saad veateate
Parser Error Message: Failed to decrypt using provider 'RsaProtectedConfigurationProvider'. Error message from the provider: The RSA key container could not be opened.
Rakenduses töötab asi ühtemoodi, IIS ise krüptib/dekrüptib connectrionStrings osa lahti
using System.Web.Configuration;
System.Configuration.ConnectionStringsSection konnc = WebConfigurationManager.GetSection("connectionStrings") as System.Configuration.ConnectionStringsSection;
this.Label1.Text = konnc.ConnectionStrings["TurukampusConnectionString"].ConnectionString.Trim();
Blogged with the Flock Browser
Tellimine:
Postitused (Atom)