Pe scurt :
Metoda 1. Setari in Visual Studio
Vedeti
Application Settings Architecture , http://msdn.microsoft.com/en-us/library/8eyb2ct1.aspx
· Application Settings Overview , http://msdn.microsoft.com/en-us/library/k4s6c3a0.aspx
Video tutorial : http://www.youtube.com/watch?v=-JDoZU0HBBo&feature=PlayList&p=70009BDDADB00AEF&index=1
Metoda 2. In app.config - metoda rapida
Video Tutorial : http://www.youtube.com/watch?v=Axkt_KE0JX4&feature=PlayList&p=70009BDDADB00AEF&index=2
Metoda 3. In app.config – metoda sigura :
Video Tutorial : http://www.youtube.com/watch?v=oglDeV7sc94&feature=PlayList&p=70009BDDADB00AEF&index=3
Metoda 4. Fisiere XML
Video Tutorial : http://www.youtube.com/watch?v=MtK3zZYjfS0&feature=PlayList&p=70009BDDADB00AEF&index=0
Metoda 5. Fisiere INI
http://jachman.wordpress.com/2006/09/11/how-to-access-ini-files-in-c-net/ http://www.codeproject.com/KB/cross-platform/INIFile.aspx
Metoda 6. Baza de date
Creati o tabela cu 3 coloane :Obiect, Nume, Valoare. Accesati prin EF, L2S sau Nhibernate sau orice altceva.
Metoda 7.Registry
Video Tutorial : http://www.youtube.com/watch?v=UeBPTbWgthM&feature=PlayList&p=70009BDDADB00AEF&index=4
Mai multe detalii aici
setari globale (write once, read more). De obicei stocate in
Path.GetDirectoryName( Assembly.GetEntryAssembly().GetName().CodeBase))
setari de user (write –read). De obicei stocate in
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)
User settings ,application settings
HKCU, HKLM
Se pune problema unde se serializeaza : hard, baza de date.
http://jachman.wordpress.com/2006/09/11/how-to-access-ini-files-in-c-net/
http://www.codeproject.com/KB/cross-platform/INIFile.aspx
Puteti crea o tabela cu 3 coloane : Obiect,Nume,Valoare. Acestati cu EF, L2S , NHibernate sau orice altceva.
Downloadati codul
Tutoriale video aici
Aplicatia este www.scurt.ro si o gasiti la adresa www.scurt.ro. Este o aplicatie de shortening service ( tinyurl si bit.ly fiind unele cunoscute deja).
Documentatia aplicatiei o gasiti la adresa http://www.scurt.ro/Home/About .
Mai intii , ce vreau sa fac cu aceasta aplicatie: Vreau sa arat ca programarea este doar baza piramidei. Si ca munca pentru o aplicatie simpla este destul de mare, in plus mai trebuie tot felul de persoane - testare,raportare, administrator de BD, SEO specialist, marketing, vinzari si altii…
Aplicatia mai are citeva chestii de facut ( de ex., paginile pentru utilizatorii inregistrati, logare,erori , add-on de IE si Firefox, SEO, etc- le gasiti in documentul http://www.scurt.ro/Docs/aplicatia%20scurt.docx )
Pentru cei care ma ajuta nu pot sa le promit nimic – decit ca vor fi mentionati printre autori –si vor avea link pus pe o pagina care trebuie definita.
Cine vrea sa ma ajute, va rog sa cititi documentul, downloadati sursele – si vorbim pe email!
Multumesc,
Andrei
Deocamdata o sa facem doar tabelele pentru detaliile/resursele care tin de un Angajat . Hai sa enumeram citeva :
(Daca aveti si alte sugestii,va rog sa imi scrieti)
Evident ca am putea creea o tabela prin care sa avem , ca si coloane, toate aceste proprietati - dar aplicatia nu ar fi destul de flexibila, in cazul in care cineva ar vrea sa mai adauge un detaliu/resursa ar trebui sa refacem aplicatia. Asa incit totul se rezolva cu un nivel de indirectare – o sa creez o tabela care sa contina gruparile de Proprietati (UserRelated, JobRelated , ITRelated) –, una care sa contina Proprietatile( nume, prenume, poza, telefon, laptop, email, etc) si una care sa faca legatura intre ele. De asemenea , trebuie ca tabelele sa contina date despre cine a introdus informatia si pina cind e valabila – acestea vor fi 3 cimpuri, continute tot timpul in (aproape) fiecare tabela , de tipul :
[DateModified<NumeTabela>] [datetime] NULL, --data modificarii
[NameUserModified<NumeTabela>] [nvarchar](150) NULL, - nume utilizator care a modificat
[IPModified<NumeTabela>] [nvarchar](150) NULL, -- ip-ul de la care s-a produs modificarea
Deocamdata am ajuns la urmatoarea structura :
Pentru conformitate , iata scriptul de creere al tabelelor si scriptul de creere a resurselor/detaliilor Angajatului.
http://serviciipeweb.ro/iafblog/content/binary/net35/bd/1/db.zip
Ce vreau sa fac in continuare este sa fac coloana ValueBinaryUserGroupProperty de tipul FileStream – adica sa isi pastreze datele pe hard, de fapt.
Verificam ca serverul suporta filestream – click dreapta pe server, “properties”, selectati “Advanced” si verificati ca filestream este OK:
Apoi click dreapta pe baza de date, “properties”, selectati FileGroups si acolo adaugati un filestream(bifati si “default”)
Acum trebuie sa adaugam un file ca sa putem profita de acest filestream . Trebuie ales File_Type : “filestream data”, filegroup-ul si, cel mai important, folder-ul in care sa il punem (ca alegere usoara, este acelasi folder ca fisierul primar de date)
Acum putem sa construim tabela noastra cu filestream – stergem tabela accUserGroupProperty (drop table accUserGroupProperty ) si o creeam cu suport de FileStream :
CREATE TABLE [dbo].[accUserGroupProperty](
[IDUserGroupProperty] [uniqueidentifier] NOT NULL ROWGUIDCOL PRIMARY KEY,
ToDateUserGroupProperty datetime NULL,
[ValueTextUserGroupProperty] [nvarchar](max) NULL,
[ValueBinaryUserGroupProperty] [varbinary](max) FileStream NULL,
[IDUser] [bigint] NOT NULL,
[IDProperty] [bigint] NOT NULL,
[DateModifiedUserGroupProperty] [datetime] NULL,
[NameUserModifiedUserGroupProperty] [nvarchar](150) NULL,
[IPModifiedUserGroupProperty] [nvarchar](150) NULL,
)
Ce ne trebuie neaparat pentru o coloana de tipul FileStream :
Cu ce ne afecteaza : cu aproape nimic – dar e bine sa poti vedea fisierele pe hard * de ex., poza angajatului o sa fie direct pe hard in loc sa o stocam in BD.
Nu uitati ca tot ce am facut aici prin click-uri se poate face si prin script, cu ajutorul butonului “Script” – se poate gasi usor in toate pozele precedente
Tema pentru acasa : Creeati o baza de date cu support filestream, o tabela cu o coloana filestream si inserati un text. Observati modificarile de pe folder-ul unde ati spus sa se creeze FileStream.
Lecturi Recomandate:
FileStream cu SQL Server (pe scurt)
http://blogs.microsoft.co.il/blogs/bursteg/archive/2008/05/09/sql-server-2008-filestream-part-1.aspx
Database normalization
http://en.wikipedia.org/wiki/Database_normalization
Developing Time Oriented databases in SQL
http://www.cs.arizona.edu/people/rts/tdbbook.pdf
Va sfatuim sa cititi partile anterioare
Primul pas : instalarea software-ului free
Al doilea pas : Analiza aplicatiei
Al treilea pas : Structura Bazei de date
Sau tutorialul anterior despre .NET 2.0
http://serviciipeweb.ro/iafblog/content/binary/tutorial.pdf
Vom importa datele din fisierul Excel in Baza de date. Daca am avea SQL Server Standard( sau mai mare) am putea importa direct din Excel in SQL Server.Este suficient sa facem click dreapta pe baza noastra de date , Tasks=> ImportData – ca in figura alaturata :
Dupa ce apasam, vom selecta la surse Excel:
Iar la destinatie serverul local de SQL Server
Cam asta ar fi, daca am avea SQL Server Standard.
Dar ,pentru ca avem SQL Server Express, nu avem o astfel de facilitate incorporata - asa ca va trebui sa ne descurcam importand datele cu un program in C#.
Vom creea tabele in SQL Server asemanatoare cu structura datelor din Excel. Vom crea tabelele asa cu am facut la pasul 3. De pilda tabela cu date despre cartile de copii va arata asa:
Acum vom importa datele. Va trebui sa facem citirea datelor in Excel si apoi scrierea lor in SQL Server.
Sa le luam pe rind:
Cream un nou proiect in C# , intitulat "ImportDate" de tip Consola in folder-ul C:\book3.
Linga toate "using" mai adaugam si un "using System.Data.OleDb;" ca sa putem citi din Excel si using System.Data.SqlClient pentru conectare la SQL Server.
O sa ne folosim de faptul ca DataAdapter stie sa faca modificari de date automat. Ne facem ca citim un DataTable din SQL Server, il umplem apoi cu datele de la Excel si ii spunem lui DataAdapter sa faca insert-urile pentru noi.
Deschidem o conexiune la SQL Server si citim datele din tabela "Excel_Copii":
Pentru citirea din Excel vom folosi driverul de OLEDB.Cream o conexiune la Excel si o sa citim datele din tabela "Copii".
Deschidem o conexiune la Excel
"Provider = \"Microsoft.Jet.OLEDB.4.0\";Data Source=\"C:\\book3\\carte.xls\";Extended Properties=\"Excel 8.0;HDR=Yes;IMEX=1\"";
(daca vreti sa stiti ce ISAM aveti , vedeti cu regedit cheia
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Jet\4.0\ISAM Formats)
Deschidem o noua comanda, prin care selectam datele din Worksheetul "Copii"
oc.CommandText = "select * from [Copii$]";
(de remarcat sintaxa cu $ si paranteze drepte)
Cod complet:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.OleDb;
using System.Data.SqlClient;
using System.Data;
namespace ImportDate
{
class Program
static void Main(string[] args)
using (SqlConnection sco = new SqlConnection())
sco.ConnectionString = "Data Source=.\\sqlExpress;Integrated Security=true;Initial Catalog=Library";
sco.Open();
using (SqlDataAdapter sda = new SqlDataAdapter("select * from Excel_Copii", sco))
// construct insert
if (sda.InsertCommand == null)
SqlCommandBuilder scb = new SqlCommandBuilder(sda);
sda.InsertCommand = scb.GetInsertCommand(true);
}
System.Data.DataTable dtTransfer = new System.Data.DataTable();
sda.Fill(dtTransfer);
using (OleDbConnection odc = new OleDbConnection())
odc.ConnectionString = "Provider = \"Microsoft.Jet.OLEDB.4.0\";Data Source=\"C:\\book3\\carte.xls\";Extended Properties=\"Excel 8.0;HDR=Yes;IMEX=1\"";
odc.Open();
using (OleDbCommand oc = new OleDbCommand())
oc.CommandType = System.Data.CommandType.Text;
oc.Connection = odc;
//fill data table with Excel data
System.Data.DataTable dtExcel = new System.Data.DataTable();
using (OleDbDataReader sr = oc.ExecuteReader())
dtExcel.Load(sr);
// transfer rows
foreach (DataRow dr in dtExcel.Rows)
DataRow drNew = dtTransfer.NewRow();
drNew.ItemArray = dr.ItemArray;
dtTransfer.Rows.Add(drNew);
sda.Update(dtTransfer);
La fel se importa si datele din tabela de SF.
Acum este cazul sa importam datele in tabele.
Mai intii, cea de autori.
Va trebui sa luam autorii din toate tabelele .
SELECT
[Autor1] as autor
FROM [Library].[dbo].[Excel_Copii]
union
select [Autor2]
UNION
FROM [Library].[dbo].[Excel_SF]
Observam urmatoarele date:
NULL
ISPIRESCU Petre
Andersen
George Lucas
Ion Creanga
Isaac Asimov
Petre Ispirescu
Va trebui sa facem 2 lucruri:
Punctul 1 este destul de usor de facut cu un update ...
update Excel_Copii set Autor1= 'Petre Ispirescu' where Autor1 = ' ISPIRESCU Petre'
Punctul 2 il vom face inserind in tabela de persoane si pe urma in tabela de Autori
INSERT INTO [Library].[dbo].[Person]
([FirstNamePerson],[LastNamePerson]
select autor,'' from
(
) a where a.autor is not null
Acum separam nume de prenume:
UPDATE
Person
SET
FirstNamePerson = substring(FirstNamePerson,1,charindex(' ' ,FirstNamePerson)-1),
LastNamePerson = substring(FirstNamePerson,charindex(' ' ,FirstNamePerson)+1,100)
WHERE charindex(' ' ,FirstNamePerson)>0
Rezultatul este:
IDPerson FirstNamePerson LastNamePerson DateOfBirthPerson
2 Andersen NULL
3 George Lucas NULL
4 Ion Creanga NULL
5 Isaac Asimov NULL
6 Petre Ispirescu NULL
Acum le vom insera in tabela de Autori:
INSERT INTO
[Author]
([IDPerson]
SELECT IDPerson FROM Person
La fel inseram cartile si editurile..
Acum trebuie sa refacem legaturile, de pilda, intre autori si carti
INSERT INTO [Book_Author]
([IDBook]
,[IDAuthor])
select IDBOOK,IDAuthor from Book b
inner join Excel_SF excel
inner join Person p on excel.Autor1 = p.FirstNamePerson + ' ' + p.LastNamePerson
inner join Author a on p.IDPerson = a.IDPerson
on excel.Titlu = b.Title
La fel si pentru carti cu edituri :
update book
set IDPrintingHouse =
p.IDPrintingHouse from Book b
inner join PrintingHouse p on p.NamePrintingHouse = excel.Editura
Ramine la latitudinea cititorului exercitiul cu celelalte update-uri.
Backupul la BD il gasiti in folder-ul database si se numeste "lib_date_importExcel.bak" . Puteti face restore.
De citit:
Surse
Tutorial PDF
Facind deja (minima) analiza a aplicatiei, putem acum sa vorbimdespre structura bazei de date. Vom face direct o baza de date relationala in cea de a treia forma normala. Pentru aceasta pornim SQL Server Management Studio Express,ne logam la serverul local (./ sau ./sqlexpress, depinde cum ati numit instanta) prin Windows authentication (cea mai simpla metoda) si click dreapta pe Databases => New Database
Numele pe care o sa i-l dam o sa fie "Library" si o sa concepem tabelele ca fiind replica exacta a obiectelor.
Vom crea tabelele direct din "Database Diagrams" Raspundem cu "Yes" la intrebarea despre "Diagram support"
Si cream o diagrama noua, numita "Library".Click dreapta, "New Table", "Person". Adaugam coloanele ca in figura, cu mentiunea ca "IDPerson" o facem "Identity" si Primary Key
Acum vom creea tabela Author – aceasta va contine o IDPerson – evidentiere a faptului ca orice Autor este si o persoana. La fel, IDAuthor este PK si Identity
Vom"trage" IDPerson din tabela Author peste IDPerson din tabela "Person", obtinind in acest fel legatura intre Autor si Persoana.
La fel si pentru celelalte tabele.
In final vom avea urmatoare structura :
Vom face un backup al Bazei de date ca in figura:
Puteti crea BD singuri sau puteti face "restore" la ea dupa acest backup , numit lib_empty.bak
Surse aici
http://serviciipeweb.ro/iafblog/content/binary/net3/20080226.zip
Acest tutorial in intregime aici
Data viitoare vom importa datele din Excel in SQL Server.
Va sfatuim sa cititi prima parte, Primul pas : instalarea software-ului free
Sau tutorialul anterior despre .NET 2.0 http://serviciipeweb.ro/iafblog/content/binary/tutorial.pdf
Aplicatia pe care o sa o facem este una de gestionare(management, pe stil nou) a cartilor dintr-o biblioteca publica. Presupunem ca biblioteca deja isi tine o evident a cartilor intr-un Excel cu o multitudine de sheet-uri, cam de aceasta forma
Un sheet, numit "Copii" care contine carti pentru copii,cu urmatoarele date:
Titlu
Autor1
Autor2
editura
Pret
Imprumutata de
Data imprumutului
Craiasa zapezii
Teora
3
Ignat Andrei
15/01/2008
GREUCEANU SI ALTE POVESTI
All
5
Capra cu trei iezi
Polirom
2
Ursul păcălit de vulpe
Zana muntilor
Alt sheet, numit SF, cu urmatoarele date
Editura
Caverne de otel
15
Fundatia
31
Fundatia si imperiul
23
Fundatia si Pamantul
21
Inainte de fundatie
13
RAZBOIUL STELELOR
54
Pare destul de clar , nu ? Fiecare carte are cite o fisa in carte, care spuen cine a imprumutat-o si cind.
Puteti downloada fisierul Excel de la adresa http://serviciipeweb.ro/iafblog/content/binary/carte.xls
Daca nu aveti Excel (?) , puteti downloada Excel Viewer
Acum vom face o mica analiza a datelor existente , pentru ca cerintele aplicatiei, ca de obicei, sunt vagi : "sa faca o cautare intre datele existente si sa reproduca procesul existent..."
E clar ca avem de a face cu urmatoarele obiecte:
Editura – ca atribute: nume, site, email
Persoana – nume, prenume, data nasterii
Autor – este o Persoana care in plus are ca atribut – site,(una sau mai multe) Carti publicate
Bibliotecare – este o Persoana cu drepturi de modificare Carti/Edituri/Autori/Setari
Client – Este o Persoana care are dreptul sa imprumute un numar(Setare) de Carti pe o perioada data (Setare)
Carti – ca atribute : Nume, data aparitiei, (publicata de ) Editura, (unul sau mai multi) Autori, ISBN, pret
Setari – Numar de carti imprumutate, Perioada imprumutului
Nu voi lua in considerare multe alte lucruri, ca de pilda faptul ca un client pierde o carte sau ca preturile pot fi modifiacte in timp ...Ar complica in mod inutil aplicatia – care nu vrea sa fie o aplicatie completa, ci doar un demo.
Data viitoare o sa facem designul Bazei de date.
Acest pas se efectuează o singura date pe PC. Este vorba despre instalarea server-ului de Web , precum si a Visual Studio Express ca si unealta de dezvoltare. Este cel mai lung pas, dar, precum am spus, se efectuează o singura data.
Să începem: ai Windows (XP, de preferinţă) si ne asiguram ca ai server-ul de Web (Internet Information Services – IIS de acum înainte) pe maşină .Pentru aceasta te duci in "Control panel" => "Administrative Tools" si verificaţi ca există.
Daca nu exista, mergeţi înapoi la "Control Panel", apăsaţi pe "Add or Remove programs" si apăsaţi pe "Add/Remove Windows Components". Bifaţi IIS ca in imagine si daţi "Next"( asiguraţi-vă ca aveţi CD-ul de instalare Windows prin apropiere)
Bun – acum o sa instalam VS 2008 Express. Acesta este free si îl puteţi descărca de la adresa
http://www.microsoft.com/express/download/offline.aspx. Acolo gasiţi o imagine ISO pe care o puteti downloada . O puteţi vedea cu ISObuster, Daemon Tools or Virtual CloneDrive ( căutaţi-le pe google pentru linkuri de download) sau cu un program făcut de MS, Virtual CD-ROM Control Panel for Windows XP care poate fi downloadat de la adresa:
http://download.microsoft.com/download/7/b/6/7b6abd84-7841-4978-96f5-bd58df02efa2/winxpvirtualcdcontrolpanel_21.exe
( da, ştiu, e o adresa scurta)
De asemenea, instalati SQL Server Express Edition with Advanced Services SP2 de la adresa http://www.microsoft.com/express/sql/download/default.aspx
Si tool-ul de administrare grafica, numit Microsoft SQL Server 2005 Express Edition Toolkit, de la aceeasi adresa http://www.microsoft.com/express/sql/download/default.aspx
Download pdf de aici:
http://serviciipeweb.ro/iafblog/content/binary/tutorialnet3.pdf
Haideti sa repetam ceea ce am facut in ASP.NET pentru WindowsForms
Deschideti Book.sln, adaugati o noua forma in proiect(frmPublisherPrint.cs) si trageti ReportViewer in forma.(Daca nu il gasiti, click dreapta in Toolbox, alegeti “choose items” , cautati ReportViewer din namespace-ul Microsoft.Reporting.WinForms si selectati-l
Adaugam raportul existent prin click dreapta pe BookWin
Va duceti in BookWeb, alegeti din casuta “Files of type” ultima selectie “All files” si selectati rptPublisher.rdlc.
Acum click pe el si in fereastra de proprietati alegeti la “Copy to output directory “ “Copy always”
Bun – acum au ramas 3 lucruri de facut : vizualizarea formei ca actiune, legarea controlului de raportul existent si codul de incarcare a datelor in raport.
Pentru vizualizarea formei ca actiune adaugati un buton btnPrint in frmPublisherList iar pe eveniment scrieti urmatorul cod:
private void btnPrint_Click(object sender, EventArgs e)
frmPublisherPrint p = new frmPublisherPrint();
p.ShowDialog(this);
Pentru legarea controlului vom seta la proprietati calea catre raport(presupunem ca se va afla in acelasi folder) si processing mode la local
Ultimul lucru de facut – incarcarea colectiei pe evenimentul de load :
rivate void frmPublisherPrint_Load(object sender, EventArgs e)
BookObjects.ColPublisher publishers = new BookObjects.ColPublisher();
publishers.Load();
MessageBox.Show(""+publishers.Count);
ReportDataSource rds = new ReportDataSource("DataSet1_Publisher", publishers);
rptPublisher.ProcessingMode = ProcessingMode.Local;
rptPublisher.LocalReport.DataSources.Clear();
rptPublisher.LocalReport.DataSources.Add(rds);
rptPublisher.LocalReport.Refresh();
rptPublisher.RefreshReport();
( exact acelasi cod ca la Web, in afara liniei :
Ea previne cazul( des intilnit) in care editorul IDE adauga , cu de la sine putere, un ReportDataSource .
Ceea ce se va infatisa va fi:
Ce mai e de facut
1)frmPublisherPrint sa nu mai afiseze ce vrea ea - ci sa primeasca un argument(in constructor, de exemplu) care sa spun ce lista de publisher-i are de afisat
2) Avind in vedere ca rapoartele sunt aceleasi pentru Windows si Web , ar fi interesant de facut un dll care sa intoarca raport – ul cerut
Orice aplicatie trebuie sa aiba posibilitatea de a tipari datele. Pentru aceasta in VS2005 Express se poate folosi componenta Report Viewer care e free si se poate downloada de la http://www.gotreportviewer.com.
Dupa ce o instalati, o sa aveti in toolbox urmatoarea componenta:
Acum adaugam un raport care sa fie afisat de catre aplicatie – deschidem aplicatia Web si adaugam un nou item de tipul Report si il numim rptPublisher.rdlc :
Acum adaugam un nou datasource apasand pe Add New DataSource
In ecranul urmator apasam pe NewConnection si selectam baza noastra de date:
Putem salva conexiunea in Web.Config(desi o mai avem) si apasam Next. Pe urmatorul ecran lasam selectat “Use SQL Statements” si iarasi Next. Acum scriem codul pentru SQL:
SELECT IDPublisher, NamePublisher, SitePublisher
FROM Publisher
si iarasi Next pina se termina ( sau direct Finish).
Acum in WebSite DataSource ne-a aparut dataset-ul care contine Publisher
Ne ducem pe Toolbox si tragem pe rptPublisher.rdlc un Table
Ne intoarcem pe WebSite DataSources si tragem Name Publisher pe detaliu:
Acum sa verificam
Cream o noua pagina aspx, frmPublisherReport.aspx si scriem urmatorul cod(sau tragem controlul de ReportViewer si ii spunem care e raportul)
<%@ Page Language="C#" MasterPageFile="~/Book.master" AutoEventWireup="true" CodeFile="frmPublisherReport.aspx.cs" Inherits="frmPublisherReport" Title="Report Publisher" %>
<%@ Register Assembly="Microsoft.ReportViewer.WebForms, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
Namespace="Microsoft.Reporting.WebForms" TagPrefix="rsweb" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
<rsweb:ReportViewer ID="rptPublisher" runat="server">
<LocalReport ReportPath="rptPublisher.rdlc">
</LocalReport>
</rsweb:ReportViewer>
</asp:Content>
In codul C# punem urmatoarele linii :
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using Microsoft.Reporting.WebForms;
public partial class frmPublisherReport : System.Web.UI.Page
protected void Page_Load(object sender, EventArgs e)
ReportDataSource rds = new ReportDataSource("DataSet1_Publisher",publishers);
Si modificam fisierul rdlc deschizindu-l cu notepad-ul si scriind urmatoarele:
<?xml version="1.0" encoding="utf-8"?>
<Report xmlns="http://schemas.microsoft.com/sqlserver/reporting/2005/01/reportdefinition" xmlns:rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner">
<DataSources>
<DataSource Name="BookConnectionString">
<ConnectionProperties>
<ConnectString />
<DataProvider>SQL</DataProvider>
</ConnectionProperties>
<rd:DataSourceID>c649d533-64c3-42b6-9805-19adbfccd468</rd:DataSourceID>
</DataSource>
</DataSources>
<BottomMargin>1in</BottomMargin>
<RightMargin>1in</RightMargin>
<rd:DrawGrid>true</rd:DrawGrid>
<InteractiveWidth>8.5in</InteractiveWidth>
<rd:SnapToGrid>true</rd:SnapToGrid>
<Body>
<ReportItems>
<Table Name="table1">
<Footer>
<TableRows>
<TableRow>
<TableCells>
<TableCell>
<Textbox Name="textbox7">
<rd:DefaultName>textbox7</rd:DefaultName>
<ZIndex>1</ZIndex>
<Style>
<PaddingLeft>2pt</PaddingLeft>
<PaddingBottom>2pt</PaddingBottom>
<PaddingRight>2pt</PaddingRight>
<PaddingTop>2pt</PaddingTop>
</Style>
<CanGrow>true</CanGrow>
<Value />
</Textbox>
</ReportItems>
</TableCell>
</TableCells>
<Height>0.45833in</Height>
</TableRow>
</TableRows>
</Footer>
<Left>0.5in</Left>
<DataSetName>DataSet1_Publisher</DataSetName>
<Top>0.25in</Top>
<Width>6.5in</Width>
<Details>
<Textbox Name="txtName">
<rd:DefaultName>Name</rd:DefaultName>
<Value>=Fields!Name.Value</Value>
</Details>
<Header>
<Textbox Name="textbox1">
<rd:DefaultName>textbox1</rd:DefaultName>
<ZIndex>2</ZIndex>
<Value>Name</Value>
</Header>
<TableColumns>
<TableColumn>
</TableColumn>
</TableColumns>
<Height>1.375in</Height>
</Table>
<Height>2in</Height>
</Body>
<rd:ReportID>9f0247a8-15fe-4ef9-962e-c4c670524163</rd:ReportID>
<LeftMargin>1in</LeftMargin>
<DataSets>
<DataSet Name="DataSet1_Publisher">
<rd:DataSetInfo>
<rd:ObjectDataSourceType>Publisher</rd:ObjectDataSourceType>
<rd:TableName>Publisher</rd:TableName>
</rd:DataSetInfo>
<Query>
<rd:UseGenericDesigner>true</rd:UseGenericDesigner>
<CommandText />
<DataSourceName>BookConnectionString</DataSourceName>
</Query>
<Fields>
<Field Name="IDPublisher">
<rd:TypeName>System.Int32</rd:TypeName>
<DataField>IDPublisher</DataField>
</Field>
<Field Name="Name">
<rd:TypeName>System.String</rd:TypeName>
<DataField>Name</DataField>
<Field Name="Site">
<DataField>Site</DataField>
</Fields>
</DataSet>
</DataSets>
<Width>9.75in</Width>
<InteractiveHeight>11in</InteractiveHeight>
<Language>en-US</Language>
<TopMargin>1in</TopMargin>
</Report>
Acum , rulind pagina, observam ca se poate exporta raportul in Excel si PDF – mai mult decit sufficient:
Data viitoare vom vedea acelasi raport in WindowsForms...
Linkuri utile:
http://www.gotreportviewer.com/ - in partea dreapta aveti exemple de aplicatii care fac diverse – genereaza automat fisierele rdlc, scot automat fisierele Excel si multe altele
SQL Server Reporting Services – pentru utilizarea avansata a rapoartelor.
Modelul asincron din ASP.NET
Sa discutam despre operatii asincrone in ASP.NET.
Exista doua tipuri mari de operatii operatii asincrone
1. Cele care se executa doar pentru operatii lungi , care iau ceva timp de executie, si pentru care user-ul trebuie instiintat de evolutia lor.
2. Cele care trimit rapid o cerere la server si se intorc.
Pentru 1.,o solutie recomandata este sa puneti Async=true in codul de pagina si sa executati codul cu RegisterTaskAsync . Asta este interesant, pina cind ne dam seama ca modul de afisare al paginii este acelasi – adica este intirziata pina cind se termina toata de executat.
Un exemplu bun gasiti aici
http://msdn.microsoft.com/msdnmag/issues/05/10/WickedCode/#S5
si aici
http://msdn.microsoft.com/msdnmag/issues/07/03/WickedCode/default.aspx
Totusi, as recomanda o alta abordare – pentru ca user-ul sa „vada” desfasurarea detaliata a actiunilor efectuate, as recomanda scrierea cu Response.Write intr-un div si ascunderea apoi a div-ului .
Ceva de genul acesta:
Pe pagina aspx, printre ultimele linii, ascunderea div-ului cu mesaje:
<script>
var mesaje = document.getElementById('mesaje');
if(mesaje != null)
mesaje.style.display = 'none';
</script>
In codul paginii aspx putem pune cod de genul urmator:
Response.Write("<div id='mesaje'>");
Response.Write("Begin :" + DateTime.Now.ToString("yyyy MMM dd hh:mm:ss") + "<BR>");
Response.Flush();
//executare prim task
Response.Write("Generated prim task<BR>");
//executare al doilea task
Response.Write("Generated al doilea task<BR>");
//incheiere procedura...
Response.Write("</div>");
Acest model se poate combina cu evenimente generate in cadrul task-ruilor astfel incit, daca task-urile dureaza prea mult, user-ul sa aiba totusi un feedback despre ceea ce se intimpla.
Sa discutam acum despre 2, executarea de operatii rapide pe server. Sa dam un exemplu simplu, si anume cautarea de publisher dupa nume. Ar fi superb daca aplicatia noastra, la apasarea primei litere a publisher-ului, ar putea sa sugereze publisher-ii care incep cu litera respectiva.
Pentru aceasta vom folosi Ajax, si vom folosi implementarea de AutoComplete de la Ajax Control Toolkit
Mai intii ,trebuie sa downloadam Ajax1.0 de aici.
Apoi va trebui sa modificam Web.Config astfel incit sa suporte Ajax.
Asta inseamna ca o sa luam o mare parte din Web.Config-ul unui site Ajax si o sa il mutam la noi in site.
Sa incepem :
De la o configuration o sa luam
<configSections>
<sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication"/>
<sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="Everywhere"/>
<section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication"/>
<section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication"/>
</sectionGroup>
</configSections>
De la system.web o sa luam
<pages>
<controls>
<add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</controls>
</pages>
Si
<compilation debug="false">
<assemblies>
<add assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add assembly="System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
<add assembly="System.Web.Extensions.Design, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/></assemblies>
</compilation>
Apoi Handler-e si Module:
<httpHandlers>
<remove verb="*" path="*.asmx"/>
<add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="false"/>
</httpHandlers>
<httpModules>
<add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</httpModules>
Apoi extensions si WebServer:
<system.web.extensions>
<scripting>
<webServices>
<!-- Uncomment this line to customize maxJsonLength and add a custom converter -->
<!--
<jsonSerialization maxJsonLength="500">
<converters>
<add name="ConvertMe" type="Acme.SubAcme.ConvertMeTypeConverter"/>
</converters>
</jsonSerialization>
-->
<!-- Uncomment this line to enable the authentication service. Include requireSSL="true" if appropriate. -->
<authenticationService enabled="true" requireSSL = "true|false"/>
<!-- Uncomment these lines to enable the profile service. To allow profile properties to be retrieved
and modified in ASP.NET AJAX applications, you need to add each property name to the readAccessProperties and
writeAccessProperties attributes. -->
<profileService enabled="true"
readAccessProperties="propertyname1,propertyname2"
writeAccessProperties="propertyname1,propertyname2" />
</webServices>
<scriptResourceHandler enableCompression="true" enableCaching="true" />
</scripting>
</system.web.extensions>
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<modules>
<add name="ScriptModule" preCondition="integratedMode" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</modules>
<handlers>
<remove name="WebServiceHandlerFactory-Integrated"/>
<add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add name="ScriptResource" preCondition="integratedMode" verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</handlers>
</system.webServer>
Acum downloadam Ajax Control Toolkit si vom referentia controalele existente, aflate in AjaxControlToolkit-NoSource\SampleWebSite\Bin . Vom adauga un nou tab in ToolBox, ii vom zice AjaxControls si vom adauga itemii apasind pe Choose Items:
Si apoi indicind prin browse calea la AjaxControlToolkit.dll pe care l-am downloadat. Apasati pe urma OK si vom avea controalele Ajax.
Trageti un AutoCompleteExtender si un textbox in frmPublisherList.aspx .
Vom completa
public class wsPublisher : System.Web.Services.WebService {
cu atributul
[System.Web.Script.Services.ScriptService]
si vom adauga o metoda pentru regasirea publisher-ilor care incep cu o litera data:
[WebMethod]
public string[] GetCompletionPublishers(string prefixText, int count)
if (count <= 0)
count = 10;
List<string> items = new List<string>(count);
foreach (BookObjects.Publisher pub in publishers)
if (pub.Name.IndexOf(prefixText, StringComparison.CurrentCultureIgnoreCase) == 0)
items.Add(pub.Name);
if (items.Count == count)
break;
return items.ToArray();
O vom folosi in Autocomplete:
<asp:ScriptManager runat="server">
</asp:ScriptManager>
<asp:TextBox ID="txtPub" runat="server" autocomplete="off"></asp:TextBox>
<cc1:AutoCompleteExtender ID="AutoPub" runat="server"
TargetControlID="txtPub"
ServicePath="wsPublisher.asmx"
ServiceMethod="GetCompletionPublishers"
MinimumPrefixLength="1"
CompletionInterval="1000"
EnableCaching="true"
CompletionSetCount="12">
</cc1:AutoCompleteExtender>
In momentul de fata putem testa aplicatia si vedea ca se listeaza numele publisher-ilor.
Lucruri de facut:
Creat o metoda prin care sa se poata incarca doar cei care au prefix, nu toti publisher-ii cum am facut in public string[] GetCompletionPublishers(string prefixText, int count)
De pus scriptManager-ul in Master- ca sa nu fim nevoiti sa il punem in fiecare pagina.
De vazut celelalte controale de la Ajax Control Toolkit (live demo la adresa http://ajax.asp.net/ajaxtoolkit/Default.aspx )
Data viitoare vom vorbi despre scoaterea de rapoarte .
De ce taskuri asincrone ? In ideea ca , intr-o aplicatie Windows(si chiar ASP.NET) , operatiile lungi ar trebui sa fie executate de catre alt thread, urmind ca aplicatia sa poata sa mai afiseze ceva utilizatorulu in tot acest timp ( fie si un buton pe care scrie „apasa ca sa intrerupi operatia asta lunga ...”). De pilda, in aplicatia noastra, daca avem mai mult de 100 de Publisher-i si vrem sa ii vedem pe toti – ar trebui incarcati intr-un nou thread.
Ne ocupam mai intii de o aplicatie Windows Forms si pe urma de ASP.NET
Un thread nu e greu de pornit. Hai sa vedem un exemplu:
System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(StartAction));
t.Start("obiect transmis");
public void StartAction(object o)
string s = o.ToString();
System.Threading.Thread.Sleep(5000);
//executa actiunea
//trimite text
if (this.InvokeRequired)
this.Invoke((MethodInvoker)delegate()
this.Text = s;
});
//sau
//this.Invoke(new MethodInvoker(evenimentfaraparametri());
//this.Invoke(new EventHandler(btnDiscounts_Click));
//this.BeginInvoke(new EventHandler(eveniment cu parametri));
else
Totusi, exista o problema – dintr-un thread nu se pot accesa DIRECT controale din alt thread – si de aceea avem instructiunea this. Invoke .Diferenta intre this.Invoke si este this.BeginInvoke aceea ca prima instructiune asteapta rezultatul actiunii, pe cind a doua doar executa si se intoarce imediat sa execute codul ramas.
De aceea exista controlul numit BackgroundWorker – care asigura ca , din evenimentul propriu generat, sa accesezi orice obiect de pe forma. O sa facem acest lucru pentru salvarea in XML a colectiei de Publisher-i in format XML.
.NET are o forma usoara de a salva o colectie/clasa in format XML , salvindu-i proprietatile.
Vom utiliza modalitatea cea mai usoara de a face acest lucru
Marcam clasa Publisher si clasa colectie ColPublisher cu atributul de [Serializable] :
[Serializable]
public class ColPublisher : System.Collections.ObjectModel.KeyedCollection<string,Publisher>
public class Publisher
Acum o sa facem serializarea obiectului Publisher:
#region Serializer
/// <summary>
/// instanta pentru lazy load
/// </summary>
private static XmlSerializer m_Serializer;
/// serializator pentru obiectul publisher
private static XmlSerializer Serializer
get
if (m_Serializer == null)
m_Serializer = new XmlSerializer(typeof(Publisher));
return m_Serializer;
/// salveaza obiectul ca XML
[XmlIgnore]
public string XML
StringBuilder sb = new StringBuilder();
EncodingStringWriter sw = new EncodingStringWriter(sb, Encoding.Default);
XmlTextWriter xtw = new XmlTextWriter(sw);
Serializer.Serialize(xtw, this);
return sb.ToString();
/// recreeeaza un Publisher dintr-un string XML
/// <param name="XML">string care contine tot </param>
/// <returns></returns>
public static Publisher FromXML(string XML)
StringReader sr = new StringReader(XML);
return Serializer.Deserialize(sr) as Publisher;
#endregion
Copiem apoi acelasi cod( cu citeva diferente) si pentru ColPublisher
Citeva comentarii despre cod:
De ce am pus [XmlIgnore] peste public string XML ? Pentru a nu serializa si aceasta proprietate, dind astfel nastere la o nedorita recursivitate
Ce e cu clasa EncodingStringWriter ? Este facuta pentru a putea schimba Encoding=ul- daca aveti de exemplu caractere speciale(diacritice) romanesti/franceze/etc.
De ce metoda FromXML este statica- iar XML este pe instanta? Asa mi se pare normal – transformarea dintr-un obiect in XML sa apartina obiectului, iar din XML in obiect nu poate sa apartina unui obiect( ah, daca as fi putut scrie this = Serializer.Deserialize(sr) as Publisher !) - ci doar clasei.
Nu se poate face codul mai „generic”? Ba da- una din deosebiri ar fi ca FromXML ar trebui sa fie pe instanta...
Haideti acum in proiectul Windows sa serializam o colectie de Publisher-i.Pe forma frmPublisherList adaugam un buton btnSave, cu textul Save, dublu click si scriem urmatorul cod:
private void btnSave_Click(object sender, EventArgs e)
BookObjects.ColPublisher col = colPublisherBindingSource.DataSource as BookObjects.ColPublisher;
string strSave = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData);
strSave = Path.Combine(strSave, "pub.xml");
File.WriteAllText(strSave, col.XML);
System.Diagnostics.Process.Start(strSave);
Rulati proiectul, adaugati 2 publisher-i si apasati pe save.
Este clar ca, daca sunt multi publisher-i, procesul poate deveni prea lung si blocheaza interfata.
Haideti sa folosim background worker. Il adaugam din toolbox , il redenumim bgSave, dublu click. Luam codul din btnSave_Click, il adaugam la si pe urma scriem doar bgSave.RunWorkerAsync();
bgSave.RunWorkerAsync();
private void bgSave_DoWork(object sender, DoWorkEventArgs e)
Data viitoare o sa vorbim despre modelul asincron din ASP.NET.
In orice aplicaţie este bine sa ţinem evidenta operaţiilor făcute de utilizator( ce a modificat sau chiar ce a văzut). In acest scop putem folosi fie mecanismul de trace din .net, fie o soluţie proprie, fie Logging and Instrumentation Application Block(http://msdn2.microsoft.com/en-us/library/ms998162.aspx), fie log4net(http://logging.apache.org/log4net/
Vom utiliza in acest exemplu log4net .El suporta log-area operaţiilor in felurite moduri – in fişier, baza de date, email, telnet si multe altele.
Downloadati versiunea 1.2.10 de la adresa http://logging.apache.org/log4net/downloads.html si sa începem configurarea aplicaţiei. Copiaţi conţinutul folder-ului log4net-1.2.10\bin\net\2.0\debug in C:\Book\sharedDll si sa începem modificarea proiectului Windows pentru a înregistra ce a făcut utilizatorul
Deschidem Book.sln si deschidem App.Config. Acolo scriem următoarele imediat sub configuration:
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
<log4net>
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<File value="Log4Net.log"/>
<AppendToFile value="true"/>
<rollingStyle value="Composite"/>
<maximumFileSize value="1MB"/>
<maxSizeRollBackups value="10"/>
<datePattern value="yyyyMMdd"/>
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%d [%t] %-5p %c %m%n"/>
</layout>
</appender>
<root>
<level value="Debug"/>
<appender-ref ref="RollingLogFileAppender"/>
</root>
</log4net>
După cum se vede, folosim RollingLogFileAppender ( adică un fişier a cărui denumire va fi diferita in fiecare zi după modelul datePattern ) de tipul Composite(daca depaseste maximumFileSize atunci se creează un nou fişier in ziua respectiva).
Sa adăugam referinţa proiectului nostru (BookWin) dll-ul log4net.dll din sharedDll .Avem de făcut următoarele in Program.cs :
In funcţia Main scriem prima linie:
log4net.Config.XmlConfigurator.Configure();
apoi adăugam următorul membru in clasa Program:
public static readonly log4net.ILog logger = log4net.LogManager.GetLogger("RollingLogFileAppender");
Haide sa scriem in fişier de cite ori un utilizator adaugă un nou Publisher.
In frmPublisherAdd.cs, la evenimentul private void btnAdd_Click(object sender, EventArgs e) vom adăuga codul de log-are:
if (Program.logger.IsDebugEnabled)
Program.logger.Debug("Adaugat publisher cu numele:" + p.Name);
Cam atit e de făcut. Acum rulaţi proiectul, adaugaţi un Publisher, si o sa vedeţi un fişier log4Net.log in care scrie următoarele:
<data> [1] DEBUG RollingLogFileAppender Adaugat publisher cu numele:newpub
E interesant la log4Net ca puteţi adăuga mai mulţi appender-i, astfel ca , de pilda, sa trimită si email de cate ori o modificare e făcuta.
Observatie 1:
Pentru aplicatia Web, modificarile in Web.Config sunt aceleasi - iar in global.asax trebuie pusa linia urmatoare:
void Application_Start(object sender, EventArgs e) { // Code that runs on application startup log4net.Config.XmlConfigurator.Configure(); }
Observatie 2:
In loc sa punem codul in fiecare pagina de Web si Windowspe salvare, mai bine punem in fiecare cod de "salvare" al obiectelor- de pilda in public void Save()
Lectura obligatorie: documentaţia de log4net...
Documentarea - Scrierea de fişiere Help.
In .NET sunt doua tipuri mari de fişiere Help : Cele care produc Help pentru utilizatorul final si cele care sunt auto-generate din comentarii la cod.
Avem nevoie de următoarele:
1.Html Help Workshop – e free si puteţi sa îl downloadati de aici
http://www.microsoft.com/downloads/details.aspx?familyid=00535334-c8a6-452f-9aa0-d597d16580cc&displaylang=en. Adiţional puteţi downloada si fişiere css stil Office de aici
http://www.microsoft.com/downloads/details.aspx?FamilyId=A6A76073-0E0A-49BB-8E21-318B798B4CF6&displaylang=en
2. Pentru documentaţia codului exista înainte NDoc – dar din păcate dezvoltatorul nu mai face dezvoltarea pentru .Net 2.0( vezi http://johnsbraindump.blogspot.com/2006/07/ndoc-20-is-dead.html)
Alternativa este SandCastle (http://www.sandcastledocs.com) din care ultimul CTP este aici (http://www.microsoft.com/downloads/details.aspx?FamilyID=E82EA71D-DA89-42EE-A715-696E3A4873B2&displaylang=en).
3.De asemenea, pentru ca SandCastle e greu de utilizat din command line, exista mai multe GUI-uri pentru el – intre care vom lucra cu SandCastle Help File Builder de pe CodePlex (http://www.codeplex.com/Wiki/View.aspx?ProjectName=SHFB). O sa lucram cu ultimul release ,1.3.3.1 PROD aflat aici
http://www.codeplex.com/SHFB/Release/ProjectReleases.aspx?ReleaseId=1209
si as downloada chiar sursele ...
Începem cu documentarea codului pentru BookObjects, urmând sa trecem la generarea de Help pentru proiectul Windows.
Comentariile in C# se fac scriind trei slash-uri deasupra clasei/metodei/cimpului pe care vreţi sa le documentaţi:
/// Aceasta clasa tine toti publisher-ii
/// Mod de utilizare : folositi Load
/// varianta interna de generat cheie unica pentru un Publisher
/// <param name="item">publisher-ul</param>
protected override string GetKeyForItem(Publisher item)
Continuaţi cu toate metodele sau downloadati ultima varianta de proiect de aici:
http://serviciipeweb.ro/iafblog/content/binary/part12/book.zip
In plus, trebuie sa mai setaţi faptul ca trebuie generata documentaţia XML din proprietatile proiectului:
Acum in folder-ul C:\Book\BookObjects\bin\Debug aveţi generata documentaţia XML. Pornim SandCastle Help File Builder care arata cam asa:
Apăsam pe Add si ne ducem in C:\Book\BookObjects\bin\Debug. Acolo indicam dll-ul generat iar programul o sa „observe” si fişierul XML. Apăsam pe iconiţa de compilare si ... eroare...
Error: Unresolved assembly reference: System.Configuration (System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a) required by BookObjects
Last step completed in 00:00:02.403
După descriere vedem că ii lipseşte o referinţa la System.Configuration. Acest dll se afla in GAC (Global Assembly Cache) si o vom adăuga. In Project Properties , la Build=>Dependencies apăsaţi pe butonul cu cele 3 puncte.
Acum in ecranul următor exista un buton cu imaginea de folder si cu o icoana de o cheie care iese, iar la tooltip scrie „Add GAC dependencies”
Apăsaţi pe el si căutaţi System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a in lista care urmează.
Acum spune ca ii lipseşte un XSL(Error: The transform file 'C:\Program Files\Sandcastle\ProductionTransforms\AddOverloads.xsl' could not be loaded. The error is: Could not find file 'C:\Program Files\Sandcastle\ProductionTransforms\AddOverloads.xsl'.). Pentru asta fie downloadati un CTP de SandCastle mai vechi sau Visual Studio 2005 SDK Version 4.0 de la adresa http://www.microsoft.com/downloads/details.aspx?FamilyID=51a5c65b-c020-4e08-8ac0-3eb9c06996f4&DisplayLang=en si copiaţi XSL-ul cu pricina in folder-ul <Program Files>\ Sandcastle\ProductionTransforms, alături de celelalte.
Acum rulati din nou si ceea ce se va genera este un document chm , numit Documentation.chm aflat in C:\Book\BookObjects\bin\Debug\Help:
Putem personaliza ceea ce se generează destul de uşor, modificând setările de aici:
E clar acum ca aceasta documentaţie se poate regenera la cerere.
Sa generam acum documentaţia pentru Windows Forms.
Ar trebui pentru fiecare forma sa avem cate un Help – aşa ca o sa cream 3 fişiere HTML care o sa tina List, Add si Update.
Vom crea un nou folder, numit HelpWindows, in C:\book\Help si vom pune in el cele 3 fişiere : add.htm,list.htm,update.htm.
Pornim HTML Help Workshop, File=>New =>Project si daţi next. Adaugati fişierele htm si apăsati pe Contents. Acceptaţi creerea unui nou fişier si apăsând pe iconiţa din stânga cu aspect de fişier adăugat la conţinut cele 3 fisiere, dindu-le numele corespunzătoare. Acum, după compilare, s-a generat un fişier chm. Haideţi sa îl integram cu aplicaţia Windows.
Sarcina de a copia fişierul chm lângă executabil o las cititorului, având in vedere ca am mai făcut aşa ceva(Project=>Properties=>Build Events). Sa mergem la forma de list si sa adaugam din ToolBox un control HelpProvider. LA proprietati la HelpNameSpace puneti numele chm-ului. Acum pe forma, gasiti HelpKeyword on... (setati valoarea la list.htm) si HelpNavigator on...( setat la topic). Rulati, apasati F1 si iata fisierul de help!
Puteti downloada ultimele surse de aici
Lecturi utile:
GAC http://www.codeproject.com/dotnet/DemystifyGAC.asp
MSHelp 2.0 http://www.helpware.net/mshelp2/h20.htm
Din mai multe motive :
1. Pentru ca e o modalitate usoara de a releva functionalitatile mari ale aplicatiei
2. Pentru ca la orice modificare la care nu sunteti sigur daca dauneaza cumva logicii aplicatiei puteti rula testele vechi si vedeti daca ati stricat ceva sau nu(Nota : ar trebui sa adaugati un nou test pentru cei care vin dupa voi )
3. E mai usor de fixat bug-urile daca, pe deasupra, rulati testele in fiecare noapte – si a doua zi dimineata vedeti ceva stricat...
4.
Hai sa trecem la treaba:
Mai intii downloadati NUnit de la http://www.nunit.org/index.php?p=download ( eu am folosit versiunea 2.2.8 )Exista si surse si setup de instalare. Eu as sfatui sa luati sursele sa le compilati.
Apoi la solutia noastra Book.sln adaugam un nou proiect de tipul Class Library , numit BookTest , adaugam o referinta la nunit.framework.dll , aflat in NUnit-2.2.8-src\src\NUnitFramework\framework\bin\Debug2005, modificam class1.cs in TestPublisher.cs si incepem sa scriem testul.Testul cel mai simplu este unul de CRUD – create , read, update, delete.
Avem nevoie de obiectele Publisher respective, precum si de setari in fisierul App.Config pentru a recunoaste Baza de date, precum si de Baza de date.
Pentru Publisher, adaugam o referinta la BookObject in tab-ul „Projects” de la Add Reference.
Pentru App.Config, adaugam un fisier de tipul application configuration file si copiem de la BookDos partile relevante, astfel incit fisierul arata astfel :
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="DatabaseUsed" value="MDB"/>
<!-- possible values : MDB, SQLServer-->
</appSettings>
<connectionStrings>
<add name="MDB" connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|\book.mdb;User Id=admin;Password=;"/>
<!-- TODO : add for asp.net application the connection string with SQL Server-->
</connectionStrings>
</configuration>
Pentru baza de date, e simplu : in Build Events, la Post Build Command Line adaugam
copy $(ProjectDir)..\BookData\*.mdb $(TargetDir)
Acum putem incepe sa scriem testul :
using NUnit.Framework;
using BookObjects;
namespace BookTest
[TestFixture] //arata ca e o clasa care contine teste
public class TestPublisher
[Test] //arata ca metoda care urmeaza este un test
[Category("CRUD")] //categoria -de obicei, testele de CRUD ar trebui puse impreuna
public void CRUD()
Publisher p = new Publisher();
p.Name = "Amazon";
p.Save();
//sa il gasim
ColPublisher cp = new ColPublisher();
cp.Load();
bool bFound= false;
foreach (Publisher pLoop in cp)
if (pLoop.Name == p.Name)
bFound = true;
//daca acea conditie(bFound) nu e true, atunci se afiseaza mesajul de eroare
Assert.IsTrue(bFound, "Nu s-a gasit publisher cu numele " + p.Name + " dupa insert");
//sa il modificam
p.Name = "O'Reilly";
p.Update();
//sa il gasim din nou
cp = new ColPublisher();
bFound = false;
Assert.IsTrue(bFound, "Nu s-a gasit publisher cu numele " + p.Name + " dupa update");
//acum sa il stergem
p.Delete();
//si sa vedem ca nu a fost gasit
//daca acea conditie(bFound) nu e false, atunci se afiseaza mesajul de eroare
Assert.IsFalse(bFound, "S-a gasit publisher cu numele " + p.Name + " dupa delete");
Il compilam si sa rulam testul. Gasiti in folderul NUnit-2.2.8-src\src\GuiRunner\nunit-gui-exe\bin\Debug2005 un nunit-gui.exe si porniti-l.Apasati File=> Open si mergeti in C:\Book\BookTest\bin\Debug si incarcati BookTest.dll . Ar trebui sa apara figura urmatoare
Apasati pe RUN si primul lucru pe care il vedeti este:
Se vede clar ca e ceva prost... ne uitam in TestPublisher.cs si vedem ca la linia 37 este
Ceva a mers prost la update ... sa vedem linia 107 din Publisher.cs
strSQL += "'" + this.Site.Replace("'", "''") + "'";
Acum e clar ce s-a intimplat ... Cind am facut testul, nu am initializat Site-ul cu nimic... si atunci este null , ceea ce inseamna ca .Replace nu poate fi aplicat
Sa modificam codul din Publisher.cs ca sa ia in seama si acest lucru :
if (this.Site == null)
strSQL += " NULL ";
Acum apare alta eroare :
Este destul de clar ca aplicatia nu a updatat numele ...
De ce ?Ne dam seama imediat : in momentul in care aplicatia a adaugat un nou Publisher , nu a regasit ID-ul inserat ... iar cind a facut update, IDPublisher este 0 , ceea ce inseamna ca nu a putut fi facut update corect.
Cum modificam acest lucru ? Pentru access , putem sa selectam maxim de ID,iar pentru SQL Server putem crea o procedura stocata ... sau sa intoarcem @@Identity
Hai sa facem pentru Access , modificand Publisher.cs, procedura Save, adaugind la final:
if(Settings.TheDatabase == Settings.DatabaseUsed.MDB)
strSQL = "select max(IDPublisher) as nr from Publisher";
using (DbConnection dc = Settings.TheConnection)
dc.Open();
using(DbCommand dco =Settings.TheCommand)
dco.CommandType = System.Data.CommandType.Text;
dco.CommandText = strSQL;
dco.Connection = dc;
object o = dco.ExecuteScalar();
this.IDPublisher = int.Parse(o.ToString());
Acum rulam din nou testul si totul e verde , ceea ce e de bine :
E clar ca exemplu a fost mai degraba simplut, iar ceea ce conteaza, de fapt, sunt regulile de business si de validare - ca de exemplu, validarea CNP
Open the book.sln solution and add a new project of type ConsoleApplication (name it BookDos)
Add reference to the BookObjects project and add an app.config file and write to this file the same as in the corresponding app.config file from BookWin application.
The post build event on project – properties must be the same as for the BookWin
In Program.cs file please enter the following code:
namespace BookDos
ColPublisher col = new ColPublisher();
col.Load();
Console.WriteLine("Records Number:" + col.Count);
foreach (Publisher p in col)
Console.WriteLine(p.Name);
And, of course, the number of records will be 0 – as we do not have any records.
In the following we will show how to perform some automated tests with NUnit .
The site map is relatively easy:
Add a new item – find “Site Map” and accept the default name (Web.sitemap)
And put the following
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
<siteMapNode url="default.aspx" title="Main" description="First Page">
<siteMapNode url="frmPublisherList.aspx" title="All publishers" description="Publishers list" >
<siteMapNode url="frmPublisher_Insert.aspx" title="New Publisher" description="Add new"></siteMapNode>
<siteMapNode url="frmPublisher_Edit.aspx" title="Edit Publisher" description="Edit"></siteMapNode>
<siteMapNode url="frmPublisher_Delete.aspx" title="Delete Publisher" description="Delete"></siteMapNode>
</siteMapNode>
<siteMapNode url="frmBookList.aspx" title="All books" description="Book list" >
</siteMap>
( the names are pretty suggestive – url, title and description)
Now it’s time to put to work :
Open Book.master , and put a site map control ( find into the navigation tab on toolbox) before content place holder:
<asp:SiteMapPath ID="SiteMapPath1" runat="server" Font-Names="Verdana" Font-Size="0.8em" PathSeparator=" : ">
<PathSeparatorStyle Font-Bold="True" ForeColor="#990000" />
<CurrentNodeStyle ForeColor="#333333" />
<NodeStyle Font-Bold="True" ForeColor="#990000" />
<RootNodeStyle Font-Bold="True" ForeColor="#FF8000" />
</asp:SiteMapPath>
And put a tree view instead of right menu:
<asp:TreeView ID="TreeView1" runat="server" DataSourceID="SiteMapDataSource1" MaxDataBindDepth="1">
</asp:TreeView>
<asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server" />
Now, if you run the project, and press new button, you will see the following
Sure that all books it is not implemented yet – but it is your task to do it.
Now we will proceed to the localization part. We want to be able that people see the content in English and French.
We will localize just one form, and we left the others as an exercise to the reader.
The setting of language will be set in a cookie on the user’s PC and will be read each time.
Add a drop down list to the master page, near Book application with the following code:
<asp:DropDownList runat="server" id="ddlLanguage" OnSelectedIndexChanged="ddlLanguage_SelectedIndexChanged" AutoPostBack="true">
<asp:ListItem Text="English" Value="en">
</asp:ListItem>
<asp:ListItem Text="French" Value="fr">
</asp:DropDownList>
On the .cs page, let’s store the actual configuration :
protected void ddlLanguage_SelectedIndexChanged(object sender, EventArgs e)
HttpCookie cookie = Request.Cookies["Language"];
cookie.Value = ddlLanguage.SelectedValue;
Response.AppendCookie(cookie);
cookie.Expires = System.DateTime.Now.AddYears(1);
Response.Redirect(Request.Url.LocalPath);
So we have saved the value ... now, let’s retrieve it:
if (!IsPostBack)
ChangeLanguage();
private void ChangeLanguage()
if (cookie == null)
//set default the cookie in web.config
string s = Thread.CurrentThread.CurrentUICulture.Name;
cookie = new HttpCookie("Language");
cookie.Value = s;
foreach (ListItem li in ddlLanguage.Items)
if (li.Value == cookie.Value)
li.Selected = true;
Now we must change the language : We can put this on each page, overriding InitializeCulture , or put in a global.asax file( that retains the application events) on Application_BeginRequest: ( new item => Global Application Class)
protected void Application_BeginRequest(object sender, EventArgs e)
string lang = System.Threading.Thread.CurrentThread.CurrentUICulture.Name;
if (cookie != null && cookie.Value != null)
lang = cookie.Value;
System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.GetCultureInfo(lang);
System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.CreateSpecificCulture(lang);
It is time now to proceed to the localization
Add an Asp.NET folder, named “App_LocalResources”
And in this folder, add three resource files, named :
frmPublisherList.aspx.en.resx
frmPublisherList.aspx.fr.resx
frmPublisherList.aspx.resx
(The file name is compose by the name of the aspx file + (optional) language + .resx )
In these files we will add just one string for the Text property of the button that is new, like in the figure:
Now, we put meta:resourcekey="btnNew" on the button:
<asp:Button ID="btnNew" runat="server" Text="New" OnClick="btnNew_Click" meta:resourcekey="btnNew"/>
And we will see in this mode the translation by changing from English to French in the combo.
Attention: if you do not have the invariant culture file ( the one without language in the name) it does not work!
If you have several items that are invariant ( like the “save” button) you can add resources to the special folder App_GlobalResources and add there resx files ( that now can be named as you want to ) As example suppose we have now in the App_GlobalResources the files
Buttons.en.resx
Buttons.fr.resx
Buttons.resx
And one resource named
btnSaveText
We can acces as so :
<%$ Resources:Buttons,btnSaveText%>
<asp:Button ID="btnSave" Text="<%$ Resources:Buttons,btnSaveText%>" runat="server" OnClick="btnSave_Click" />
Or , programatically, by writing :
Resources.Buttons.btnSaveText
Next time we will look at making a DOS project for the same application
Items to read:
Localization: http://quickstarts.asp.net/QuickStartv20/aspnet/doc/localization/localization.aspx
Master Pages:
http://quickstarts.asp.net/QuickStartv20/aspnet/doc/masterpages/default.aspx
Now we will edit the Publisher objects .
Add a new WebForm , name it frmPublisher_Insert.aspx and make sure the “Place code in separate file” and “Select master page” are both selected by default.
Change in source view the title from “Untitled Page” to “Insert Publisher”
Now we must put controls in place to insert publishers
There must be the name and site of the publisher.
I prefer enter a table for this and the page will look like this:
<%@ Page Language="C#" MasterPageFile="~/Book.master" AutoEventWireup="true" CodeFile="frmPublisher_Insert.aspx.cs" Inherits="frmPublisher_Insert" Title="Insert Publisher" %>
<table>
<tr>
<td colspan="2">Enter values
</td>
</tr>
<td>
Name
<asp:TextBox ID="txtName" runat="server">
</asp:TextBox>
Site
<asp:TextBox ID="txtSite" runat="server">
<td><asp:Button ID="btnSave" Text="Insert" runat="server" />
<td><asp:Button ID="btnCancel" Text="Cancel" runat="server" />
</table>
Now switch to design view and double click on Insert button in order to generate Click event. Double click in solution explorer the frmPublisher_Insert.aspx and , in Design view, double click on Cancel button in order to generate Click event.
For cancel it is clear what we must do – redirect to the frmPublisherList.aspx
Response.Redirect("frmPublisherList.aspx", false);
For save button, we must create a new publisher and save
p.Name = txtName.Text;
p.Site = txtSite.Text;
p.Insert();
Please try it by setting the frmPublisher_Insert.aspx as start page and run the project (F5)
If all works well (please ensure that Insert has a call to Save()) you will see in the frmPublisherList.aspx the item you just selected.
It is clear that frmPublisherList.aspx has a need for a new button . Let’s put it
<asp:Button ID="btnNew" runat="server" Text="New" OnClick="btnNew_Click" />
And on code:
protected void btnNew_Click(object sender, EventArgs e)
Response.Redirect("frmPublisher_Insert.aspx", false);
That will be ok for adding a new publisher.
Now for editing and deleting we can make on list… but I prefer having 2 new pages.
So modify a little bit the code on the grid, in order to have the edit and delete operations : the edit will be a link , and the delete will be a button to see how different is the model on the two implementations.
The list page now looks like this:
<%@ Page Language="C#" MasterPageFile="~/Book.master" AutoEventWireup="true" CodeFile="frmPublisherList.aspx.cs" Inherits="frmPublisherList" Title="Publisher Lists" %>
<asp:GridView ID="grdPublisher" runat="server" AutoGenerateColumns="false">
<Columns>
<asp:BoundField DataField="Site" HeaderText="Site" />
<asp:BoundField DataField="Name" HeaderText="Name" />
<asp:TemplateField HeaderText="Operations">
<ItemTemplate>
<asp:Button runat="server" ID="btnDelete" CommandName="deletepub" CommandArgument='<%# Eval("IDPublisher") %>' Text="Delete" />
<asp:HyperLink runat="server" ID="hkEdit" NavigateUrl='<%# Eval("IDPublisher","~/frmPublisher_Edit.aspx?ID={0}") %>' Text="Edit"></asp:HyperLink>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<br />
The link hkEdit is self explanatory – it goes to the frmPublisher_Edit.aspx with the ID of publisher in the row.
For the button we must create the event – and the event is on the grid itself – is the RowCommand
On the .cs file:
protected void grdPublisher_RowCommand(object sender, GridViewCommandEventArgs e)
switch(e.CommandName)
case "deletepub":
int idPublisher;
if(int.TryParse(e.CommandArgument.ToString(),out idPublisher))
Response.Redirect("frmPublisher_Delete.aspx?ID="+ idPublisher, false);
return;
Response.Write("Can not find id:" + idPublisher);
default:
Response.Write("Do not know command : " + e.CommandName);
Now create the two pages frmPublisher_Delete and frmPublisher_Edit
On both we will copy the table from the new page and the source – without the class declaration. One more thing is to retrieve from ID the editing publisher:
if(!int.TryParse(Request.QueryString["ID"],out idPublisher))
//we have id of the publisher
How can we retrieve from the ID of the publisher the object ? Remember that in Windows forms application we did pass from one form to another the publisher object. Here we have just the Id. For this, we will open again the Book.sln solution and add the method to load one single object.
I like to put the method on ColPublisher and make it static … to not apparently create a new object.
public static Publisher sLoadFromID(int ID)
DbConnection db = Settings.TheConnection;
using (db)
db.Open();
IDataReader ir = Settings.Load("select IDPublisher, NamePublisher, SitePublisher from Publisher where IDPublisher="+ ID, db);
while (ir.Read())
p.FillObject(ir);
return p;
return null;
Compile and go to Web project.We can have the publisher:
Publisher p = ColPublisher.sLoadFromID(idPublisher);
if (p == null)//maybe someone deleted
//now fill the text boxes
txtName.Text = p.Name;
txtSite.Text = p.Site;
Why we have put (!IsPostBack ) ? Simply because the textboxes must be filled only once – the first time. When the user enter new name and/or new site and after clicks on save, we must preserve his data .Other problem is that when we have to save the data, we must have the same code to load the publisher – so we put this into a function into the page:
private Publisher pub
if (!int.TryParse(Request.QueryString["ID"], out idPublisher))
return ColPublisher.sLoadFromID(idPublisher); ;
The code on PageLoad will be now shorter :
Publisher p = pub;
if (p == null)
And we must modify the code on saving also :
protected void btnSave_Click(object sender, EventArgs e)
//TODO : throw an exception that someone deleted the publisher
You can modify also the text of btnsave from “Insert” to “Save”
On the delete page we will put the same code to retrieve the Publisher .Here is the code:
public partial class frmPublisher_Delete : System.Web.UI.Page
if(p != null)
protected void btnCancel_Click(object sender, EventArgs e)
Do not forget to change the text “Insert” of btnSave to “Delete”. You also can put readonly property to true on the textboxes
<%@ Page Language="C#" MasterPageFile="~/Book.master" AutoEventWireup="true" CodeFile="frmPublisher_Delete.aspx.cs" Inherits="frmPublisher_Delete" Title="Untitled Page" %>
<asp:TextBox ID="txtName" runat="server" ReadOnly="true">
<asp:TextBox ID="txtSite" runat="server" ReadOnly="true">
<td><asp:Button ID="btnSave" Text="Delete" runat="server" OnClick="btnSave_Click" />
<td><asp:Button ID="btnCancel" Text="Cancel" runat="server" OnClick="btnCancel_Click" />
Next time we will put some modifications to the site: a site map(in order to can have indications for the user where he is) and code to change and load resources in English and French languages at run time.
Now, it’s time to make the ASP.NET application. I suppose that you have already installed Internet Information Services (you will find in the Administrative tools folder) . If not, please install and run aspnet_regiis.exe that you will find into <WindowsPath> \Microsoft.NET\Framework\<latest version> (my path is C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727)
Install SQL Server Express(<Address>) and WebDeveloper(<Adress>) – no install of SQL because you have done this already.
Now it’s time to import our data to the SQL Database. Start SQL Server Management Studio and you will find the databases already installed.Create a new database (name: Book) and import the mdb database into this new database. Right Click on Book => Tasks= > Import data .
In the first screen choose as data source Microsoft Access
The next screen is correctly completed – as you can, use windows authentication. Choose next “Copy data from one or more table or views” and click “select all” in the following screen. You can now press Finish and make the task. Some modifications are necessary to be done: Choose Book=> Tables in SQL Server Management Studio. Right click Publisher table and press modify. We must make IDPublisher an auto number like in Access, In SQL Server, auto number is named identity. As you modify the (Is Identity) property, you will see the identity incremend and seed to be modified also in 1 and 1. Save the table. The next step is to create a folder where we create the internet program. Goto C:\Book and create a new folder , named BookWeb Now , from the Administrative Tools folder double click Internet Information Services and expand (local computer)=> WebSites=> Default Web Site.Right click Default Web Site and choose New => Virtual Directory. Click next. In the Alias please enter BookWeb. For the directory enter C:\Book\BookWeb .Press twice “Finish” and we are ready. Now we are ready to program our first page in ASP.NET. As usually we will have a list page and create/update/delete pages for Publisher.To make the possibility that the site has an unitary interface, we will create a master page –Book.master. Open Microsoft Visual Web Developer 2005 Express Edition and choose Open Web Site like in the image: Choose “Local IIS” tab and “BookWeb” as virtual directory Now we will cre In the “Solution Explorer” right click the http://localhost/BookWeb and choose Add new Item – and choose Master Page and name it “Book.master”.Do not forget “ Place code in separate file” The interface of the master page will be rather simple : a table that has 2 rows and 2 column , the upper row being an unique cell The content is here: <%@ Master Language="C#" AutoEventWireup="true" CodeFile="Book.master.cs" Inherits="Book" %> <!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>Untitled Page</title> </head> <body> <form id="form1" runat="server"> <div> <table width="100%"> <tr> <td colspan="2" align="center"> Book application</td> </tr> <tr> <td width="10%"> Right menu </td> <td> <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server"> </asp:ContentPlaceHolder> </td> </tr> </table> </div> </form> </body> </html> Now the list page. Add a new Item – Web Form(frmPublisherList.aspx) – and make sure that you have checked BOTH checkboxes. The next dialog shows you the BookMaster that you must select and then press OK.Right click on the file and choose “Set as start page” In the asp:content tag drag a gridview ( found in Toolbox=> Data) . This gridview must be filled with data – so we will connect to the objects that we have created. Here is a problem – how we can found if we create for the dll a Debug or Release and bind to the apropiate folder ? The solution, as always in programming, is indirection : make a new folder , bookdll and we will copy here the sources, independently of debug or release. So we create the C:\Book\BookDll , go back to the Book solution and on Build Events copy the sources in the BookDll folder and put this line in the Post build command line: copy $(TargetDir)*.* $(ProjectDir)..\BookDll /Y Compile the project. Now you will find in the C:\Book\BookDll folder the BookObjects.dll Add a reference to the BookObjects.dll in the BookWeb application( old story : right click http://localhost/BookWeb project, choose add reference, click Browse tab – and navigate to the C:\Book\BookDll folder. On the frmPublisherList.aspx press F7 and put this lines into the Page_load event if (!IsPostBack) BindData(); The BindData function: private void BindData() { BookObjects.ColPublisher publishers = new BookObjects.ColPublisher(); publishers.Load(); grdPublisher.DataSource = publishers; grdPublisher.DataBind();// main difference ASP and Windows forms - this call } Now , if you run the project, an error will occur : Object reference not set to an instance of an object This is because we do not add yet the web.config with database connection.add a new web configuration file ,named default Web.Config, and in the connection strings put this: <connectionStrings> <add name="SQLServer" connectionString="server=.;Trusted_Connection=true;database=Book;"/> </connectionStrings> And we must specify that we connect to the SQL . <appSettings> <add key="DatabaseUsed" value="SQLServer"/> <!-- possible values : MDB, SQLServer--> </appSettings> Now press again CTRL+F5. The error that you have now is Cannot open database "Book" requested by the login. The login failed. Login failed for user '<PCNAME>\ASPNET'. Why this error? Remember that we have put Trusted_Connection=true in the web.config. So the user that is connecting is the user that runs the site. We have more solutions : 1) Use in the web.config a connection with user name and password (good for Internet sites) 2) Run the site on other credentials for anonymous( good for internet/intranet sites) – option made in IIS like in image 3) Disable anonymous and use “Integrated windows” in collaboration with a setting in web.config file, <identity impersonate="true"/>( good for intranet sites ) 4) Create a SQL Server user for the credentials user(IUSR_ )that has rights on the database. You can make your choice…Personally, I prefer the first solution. OK.The next time we will see how to insert data on the SQL database. Recommended Readings Master Pages ConnectionStrings
The next screen is correctly completed – as you can, use windows authentication.
Choose next “Copy data from one or more table or views” and click “select all” in the following screen.
You can now press Finish and make the task.
Some modifications are necessary to be done:
Choose Book=> Tables in SQL Server Management Studio. Right click Publisher table and press modify.
We must make IDPublisher an auto number like in Access, In SQL Server, auto number is named identity.
As you modify the (Is Identity) property, you will see the identity incremend and seed to be modified also in 1 and 1.
Save the table.
The next step is to create a folder where we create the internet program.
Goto C:\Book and create a new folder , named BookWeb
Now , from the Administrative Tools folder double click Internet Information Services and expand (local computer)=> WebSites=> Default Web Site.Right click Default Web Site and choose New => Virtual Directory. Click next. In the Alias please enter BookWeb. For the directory enter C:\Book\BookWeb .Press twice “Finish” and we are ready.
Now we are ready to program our first page in ASP.NET.
As usually we will have a list page and create/update/delete pages for Publisher.To make the possibility that the site has an unitary interface, we will create a master page –Book.master.
Open Microsoft Visual Web Developer 2005 Express Edition and choose Open Web Site like in the image:
Choose “Local IIS” tab and “BookWeb” as virtual directory
Now we will cre
In the “Solution Explorer” right click the http://localhost/BookWeb and choose Add new Item – and choose Master Page and name it “Book.master”.Do not forget “ Place code in separate file”
The interface of the master page will be rather simple : a table that has 2 rows and 2 column , the upper row being an unique cell
The content is here:
<%@ Master Language="C#" AutoEventWireup="true" CodeFile="Book.master.cs" Inherits="Book" %>
<!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>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<table width="100%">
<td colspan="2" align="center">
Book application</td>
<td width="10%">
Right menu
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
</div>
</form>
</body>
</html>
Now the list page.
Add a new Item – Web Form(frmPublisherList.aspx) – and make sure that you have checked BOTH checkboxes. The next dialog shows you the BookMaster that you must select and then press OK.Right click on the file and choose “Set as start page”
In the asp:content tag drag a gridview ( found in Toolbox=> Data) .
This gridview must be filled with data – so we will connect to the objects that we have created. Here is a problem – how we can found if we create for the dll a Debug or Release and bind to the apropiate folder ? The solution, as always in programming, is indirection : make a new folder , bookdll and we will copy here the sources, independently of debug or release.
So we create the C:\Book\BookDll , go back to the Book solution and on Build Events copy the sources in the BookDll folder and put this line in the Post build command line:
copy $(TargetDir)*.* $(ProjectDir)..\BookDll /Y
Compile the project.
Now you will find in the C:\Book\BookDll folder the BookObjects.dll
Add a reference to the BookObjects.dll in the BookWeb application( old story : right click http://localhost/BookWeb project, choose add reference, click Browse tab – and navigate to the C:\Book\BookDll folder.
On the frmPublisherList.aspx press F7 and put this lines into the Page_load event
BindData();
The BindData function:
private void BindData()
grdPublisher.DataSource = publishers;
grdPublisher.DataBind();// main difference ASP and Windows forms - this call
This is because we do not add yet the web.config with database connection.add a new web configuration file ,named default Web.Config, and in the connection strings put this:
<add name="SQLServer" connectionString="server=.;Trusted_Connection=true;database=Book;"/>
And we must specify that we connect to the SQL .
<add key="DatabaseUsed" value="SQLServer"/>
Now press again CTRL+F5. The error that you have now is
Recommended Readings
Master Pages
ConnectionStrings
Now to the performing of the setup.We suppose that we want to deploy from a CD.
Right click Book win project, choose properties, and click on “Publish” tab.
There you will find the “Publishing location” – default to http://localhost/BookWin/
If you do not have IIS, then you can select a path, like C:\Book\BookSetup\
The problem that we have is that in the files that we need to install must be also the mdb file.
If you have something like a VS.NET Standard(or more) you have a special project template that allows you to add other files to the deployment. For the moment, we have to do what we can do. So, please right click the bookwin project, click add=>existing item and search for the book.mdb file from C:\Book\BookData .
Compile the project (CTRL+Shift+B) and now you will find the book.mdb on the application files – as data file.
Now to the prerequisites : Because we are deploying a CD, it is better to include .NET 2.0 – and download from the same location (when we are deploying from internet, I think it is preferable to deploy from MS site )
The updates will not be yet available, since we do not have yet a web site. But we can customize some of Options, like publisher name, product name and others.
Now press Publish Wizard :
The first step is where to make the setup kit (C:\Book\BookSetup\ already selected ) , the next is from where (click “from cd –rom or dvd rom”).
The third allows the application to check for updates – but , for the moment, we do not have a WebSite yet, so “the application will not check for updates”
And press finish!
If an error occurs, that says that can not find package, please go to Microsoft .NET Framework Version 2.0 Redistributable Package (x86) http://www.microsoft.com/downloads/details.aspx?FamilyID=0856eacb-4362-4b0d-8edd-aab15c5e04f5&displaylang=en and download the kit. Copy this kit to <C:\Program Files>\Microsoft Visual Studio 8\SDK\v2.0\Bootstrapper\Packages\DotNetFX
For instmsia.exe , goto http://go.microsoft.com/fwlink/?LinkId=37285
Now you can write the folder C:\Book\BookSetup to a CD and test .
If you do not want a CD, you can wrote a file and load as a CD.
One way is to create a ISO file with Alex Feinman IsoRecorder
http://isorecorder.alexfeinman.com/isorecorder.htm
Download his software ( I have tested the version for XP SP2 ) and right click the folder Book Setup
You will see Create ISO image file – click and accept default setting.
Now you have a CD -and you can load this CD with Virtual CD Control Panel.
You can now test the CD you have already created.
More, if you want to test on another environment, you can download Virtual PC 2004 SP1 or VMWare and create with those a new Windows Installation (of course, you must have the Windows installation CDs).
Next time we will do a ASP.NET application with SQL Server as a backend.
Suggested readings:
Comparison between VS.NET 2005 editions: http://msdn.microsoft.com/vstudio/products/compare/default.aspx
Virtual PC 2004 SP1 (free) http://www.microsoft.com/downloads/details.aspx?familyid=6d58729d-dfa8-40bf-afaf-20bcb7f01cd1&displaylang=en
Deployment problems : http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=13937&SiteID=1
Virtual CD Control Panel – http://download.microsoft.com/download/7/b/6/7b6abd84-7841-4978-96f5-bd58df02efa2/winxpvirtualcdcontrolpanel_21.exe
Alex Feinman – Make ISO http://isorecorder.alexfeinman.com/isorecorder.htm
Va trebui, asa cum am promis, sa facem adaugarea/ modificarea / stergerea de obiecte( pe scurt, C(R)UD – create, (read), update, delete). Luam un buton din Toolbox, il tragem pe forma, ii setam din proprietati ( apasati F4) numele la btnAdd si text la “&Add” ( &A e pentru ca, atunci cind apasam <ALT> + A , sa fie ca si cind dam click pe button)
Acum dati dublu click pe button – si veti intra in codul de click. Avem o problema : trebuie ca user-ul sa introduca numele Publisher-ului. O sa creeam o noua forma : Click dreapta pe BookWin, Add => Windows Form- si ii veti da denumirea de frmPublisherAdd.cs. Apasati F4 si la Text puneti : Add Publisher
Adaugati un Label( Name: lblName , Text : &Name) si un textbox ( Name : txtName)
Adaugam acum un Button de Add ( Name : btnAdd, Text : &Add) si unul de Exit (Name : btnExit, Text : E&xit)
Codul de pe btnExit e cel mai usor ( dati dublu click pe buton)
private void btnExit_Click(object sender, EventArgs e)
this.Close();//close the form
Codul de pe Button-ul de Add :
private void btnAdd_Click(object sender, EventArgs e)
BookObjects.Publisher p = new BookObjects.Publisher();
E clar ca trebuie sa scriem metoda de Save pe Publisher
Inapoi la clase : si acolo vom scrie metoda de save.
public void Save()
string strSQL = " insert into Publisher(NamePublisher";
if (!string.IsNullOrEmpty(this.Site))
strSQL += ",SitePublisher ";
strSQL += " ) Values (";
strSQL += "'" + this.Name.Replace("'","''") + "'";//terminator for string in SQL is ' - so replace with ''
strSQL += "," +"'"+ this.Site.Replace("'", "''") +"'";//terminator for string in SQL is ' - so replace with ''
strSQL += " )";
Settings.ExecuteSQL(strSQL);
In sfirsit, sa scriem codul pentru adaugare de pe forma de list:
E clar ca va trebui sa facem re incarcarea datelor - deci o sa luam codul de pe frmPublisherList_Load si o sa il punem in o functie generica , RebindData()
frmPublisherAdd f = new frmPublisherAdd();
f.ShowDialog(this);
RebindData();
private void RebindData()
colPublisherBindingSource.DataSource = publishers;
Sa verificam functionarea
Dati CTRL+ F5 , apasati Add – introduceti un nume – apasati Add – si verificati ca se vede in lista ceea ce ati introdus.
Sa facem acum stergerea.
Adaugati alt buton(Name = btnDelete, Text = &Delete) si sa scriem cod pentru delete
private void btnDelete_Click(object sender, EventArgs e)
BookObjects.Publisher p = colPublisherBindingSource.Current as BookObjects.Publisher;
if (p != null)
//avert the user
if (MessageBox.Show(this, "Delete " + p.Name, "Delete", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
In sfirsit, sa scriem codul pentru update: iarasi buton, iarasi cod
private void btnUpdate_Click(object sender, EventArgs e)
frmPublisherUpdate f = new frmPublisherUpdate(p);
Pentru asta, adaugam o alta forma, in care sa facem update .
Dar avem neaparata nevoie de un publisher pe care sa facem update.Vom modifica constructorul formei ca sa accepte ca parametru de intrare un publisher.
Ca sa punem valorile deja obtinute in text box-uri, avem 2 variante :
Fie codam de mina de doua ori ( ceva de genul txtName.Text= m_Publisher.Name si , pe salvare, m_Publisher.Name= txtName.Text),fie lucram cu DataBindings direct . Prefer acum, pentru rapiditate, a doua varianta :
public partial class frmPublisherUpdate : Form
private BookObjects.Publisher m_Publisher;
public frmPublisherUpdate(BookObjects.Publisher pub)
m_Publisher = pub;
InitializeComponent();
private void frmPublisherUpdate_Load(object sender, EventArgs e)
txtName.DataBindings.Add("Text", m_Publisher, "Name");
txtSite.DataBindings.Add("Text", m_Publisher, "Site");
m_Publisher.Update();
this.Close();
Sa scriem si codul de salvare pe publisher :
public void Update()
string strSQL = " update Publisher set ";
strSQL += " NamePublisher = ";
strSQL += "'" + this.Name.Replace("'", "''") + "'";
strSQL += ",";
strSQL += " SitePublisher = ";
strSQL += " where IDPublisher = " + this.IDPublisher;
strSQL += " ";
Ca tema de acasa, ramine sa faceti acelasi lucru pentru tabela Author.
Data viitoare o sa facem un mic refactoring de code... si o sa facem un program de setup pentru aplicatia Windows.
If you have not read yet the first parts, please found them here: Part 1 , Part 2 and Part 3
Now we have the Access database on the C:\Book\BookData – and the dll to load data is on the C:\Book\BookObjects.
We will create a Windows Forms project to see the data that is in the MDB file.
Right click on the solution -and choose: Add => New Project => and choose Windows Application. Put the name BookWin. A new form is created for you by default.
Change the name from Form1 to frmPublisherList.cs, double click on the file, press F4 to bring Properties window up front and change the Text from Form1 to List of Publishers.
Now we must tell to the windows project to use the objects project that we created earlier. Right click BookWin project in the Solution Explorer, click „Add reference” and go to the Projects tab on the next window. Double Click the BookObjects project.Compile(CTRL+SHIFT+B).
I must found a way to copy the MDB in the same location as the executable, in order that the path can function easily even the application will be deployed in other paths. (Not every user will easily agree to deploy the application on the same path as we do, C:\Book – maybe he wants to install in other places).
The solution to be always in sync is to perform the copy automatically and precisely when the build is complete.
Right click on BookWin project from Solution Explorer, select properties (or find in menu Project => Book Project Properties)
On the “build events“tab you have a pre and a post build event command line
We will wrote this code in the post build
That means copy all MDB files from the following dir C:\Book\BookData (obtained as following from the project dir (C:\Book\BookObjects\), the up (C:\Book\), the to BookData (C:\Book\BookData)) to TargetDir (does no matter if debug or release)
Save and compile (CTRL + SHIFT + B)
Now in the C:\Book\BookObjects\bin\Release or in the C:\Book\BookObjects\bin\Debug must be another copy of the MDB file.
Very good * let’s write now the connection to the MDB. Right Click on BookWin in the Solution Explorer – click Add => New Item => and choose “Application Configuration File” ( default name :App.config – do not change this!) and put the following lines:
Now it’s the moment to load the records. We put code in the settings.cs file to be able to switch connection at run-time:
public static DbConnection TheConnection
switch (TheDatabase)
case DatabaseUsed.MDB:
OleDbConnection oc = new OleDbConnection(ConnectionStringMDB);
return oc;
case DatabaseUsed.SQLServer:
SqlConnection sc=new SqlConnection(ConnectionStringSQLServer);
return sc;
// Maybe throw an error that config file has not been initialized with
// the database type ?
And to load Records:
public static IDataReader Load(string CommandLine, DbConnection dbcon)
if (!(dbcon.State == ConnectionState.Open))
dbcon.Open();
DbCommand dc = null;
dc = new OleDbCommand(CommandLine);
dc = new SqlCommand(CommandLine);
//TODO : throw specific error that database type does not properly have been initialized
dc.CommandType = CommandType.Text;
dc.Connection = dbcon;
return dc.ExecuteReader();
As you see, we return a DbConnection no matter we use the OleDbConnection or SqlConnection .
Now let’s fill in the Load code in the ColPublisher file:
using System.Data.Common;
namespace BookObjects
return "K" + item.IDPublisher;
public void Load()
IDataReader ir = Settings.Load("select IDPublisher, NamePublisher, SitePublisher from Publisher", db);
//TODO : add p into the collection
We realize now that the ColPublisher is not a collection where to add the new publisher p. Fortunately, the .NET collection is enough big to contain many collection.
Just look into the System.Collections namespace, then into System.Collections.ObjectModel and into System.Collections.Specialized. You will find many more on the net ( for example, an implementation of a Set collection : http://www.codeproject.com/csharp/sets.asp)
We will derive the ColPublisher from the System.Collections.ObjectModel.KeyedCollection<string,Publisher> .We must wrote how to generate the key for a specific Publisher -and what Key is better than the ID ?
Now we can wrote the Load method properly :
this.Add(p);
And use it from the Form :
Double click on the frmPublisherList.cs and drag a DataGridView to the form
Now configure the data source:
Click on “(none)” and select “add new data source”
In the next dialog, choose “Object”
and press next.
Now expand the BookObjects node and choose “ColPublisher”. Press Next and then Finish.
To the form is a new control added: colPublisherBindingSource – and the Grid has already the columns defined.
Now wrote the data to load the data from the database:
Double click on form, and you will find yourself in the Form_Load event :
private void frmPublisherList_Load(object sender, EventArgs e)
Now the results – right click on BookWin – and select “Set as startup project”
Now press F5 * and wait to see the results. If the best case, you will see a form with no data at all – and this is very correct – because of the fact that are no items in the Book.mdb
In the next lesson we will wrote code to do insert of a new Publisher and viewing him on the form ( finally!)
Recommended readings:
CSLA : http://www.lhotka.net/cslanet/ – a good framework to handle all the security, scalability , binding and other issues ( and, most of all, free).
Ar fi folositor sa cititi partea 1 si partea a 2-a
Acum la creearea obiectelor
Fiecare obiect trebuie sa aiba proprietati care corespund cimpurilor din Baza de date si , pentru usurinta, alte proprietati/metode
O sa scriu codul pentru Publisher si o sa las pe celelalte ca un exercitiu pentru dvoastra. Pentru a salva/sterge/creea un obiect de tip Publisher o sa implementam corespondentele metode corresponding method update / delete / insert.
Faptul ca un publisher trebuie sa aiba un nume unic o sa il scriem mai tirziu.
Stim deja ca trebuie sa avem doua baze de date, asa incit o sa avem doua stringuri de conexiune -pentru Access si pentru SQL Server)
Pentru a usura scrierea stringurilor de conexiune, va rog sa consultati www.connectionstrings.com
PEntru a vedea toate inregistrarile din tabela publisher, trebuie sa stocam undeva multimea lor. Aceasta multime va fi o clasa numita ColPublisher. Ea va contine o metoda numita Load care va incarca Publisher-ul din baza de date si le va stoca intr-o colectie.
Acum , cind stim ce avem de facut in continuare, hai sa scriem ceva cod
Start Visual C# Express( daca e prima oara cind il lansati, va va intreba setarile -puneti pe cele de C#)si creati un nou proiect numit Books
si salvati in C:\book
De obicei, the System.Data.dll este listat in referinte. Daca nu, va rog sa il adaugati. Oricum, adaugati va rog si o referinta la System.Configuration.
Click dreapta pe Solution Explorer si Add reference laOleDBConnection ca mai jos :
Redenumiti Class1.cs dinproprietati( click pe fisier in Solution Explorer si apasati F4) in Publisher.cs
Daca raspundeti "yes" la urmatoarea intrebare, numele clasei va fi schimbat din Class1 in Publisher – si faceti-o public class
Acum o sa scriem proprietatile de baza pentru un Publisher :
#region Database properties
private int m_IDPublisher;
public int IDPublisher
return m_IDPublisher;
set
m_IDPublisher = value;
private string m_Name;
public string Name
return m_Name;
m_Name = value;
private string m_Site;
public string Site
return m_Site;
m_Site = value;
Trebuie sa le incarcam aceste proprietati din Baza de date, asa incit o sa scriem o metoda Fill:
O sa o scriem astfel incit sa nu avem dependenta de BD:
#region Database methods
public void FillObject(System.Data.IDataReader idr)
this.Name = idr["NamePublisher"].ToString();
this.Site = idr["SitePublisher"].ToString();
ACum va trebui sa scriem codul de incarcare din BD a diverselor inregistrari. Asaugati o noua clasa ( Project => Add Class) si denumiti-o ColPublisher.cs.
Din nou , faceti-o public class si haide sa scriem metoda care incarca datele din BD.
ACum ne dam seama ca ne trebuie cele doua conexiuni - si o metoda de a vedea pe care din ele le incarcam.
Asa incit vom incepe sa scriem cod spre a incarca conexiunile :
public static string ConnectionStringMDB
return System.Configuration.ConfigurationManager.ConnectionStrings["MDB"];
public static string ConnectionStringSQLServer
return System.Configuration.ConfigurationManager.ConnectionStrings["SQLServer"];
Asa cum am tot spus, avem doua stringuri de conexiune.
A venit timpul sa stim cind incarcam una si cind cealalta in functia Load.
O sa adaug o noua clasa numita Settings si o sa pun acolo setarile comune
O sa adaug o enumerare care o sa imi spuna ce baza de date voi utiliza
public enum DatabaseUsed
None,
MDB,
SQLServer
si o sa o citim din fisierul de configurare(App.config sau Web.Config) :
public static DatabaseUsed TheDatabase
return Enum.Parse(typeof(DatabaseUsed), System.Configuration.ConfigurationManager.AppSettings["DatabaseUsed"];
Puteti obserava ca am pus configurarea in Appsetting . Putem stoca si stringurile de conexiune in acelasi loc - dar am vrut sa fim compatibili cu standardul Microsoft.
Codul poate fi obtinut de aici
Data viitoare o sa scriem cod pentru a incarca datele din BD si a le pune in colectie.
Pentru .NET best practices, puteti citi http://www.ssw.com.au/ssw/Standards/default.aspx
PEntru construirea unui ORM (Object-relational_mapping) cum facem aici, cititi articolul urmator de pe Wikipedia (http://en.wikipedia.org/wiki/Object-relational_mapping) si puteti gasi o lista de ORM la adresa http://en.wikipedia.org/wiki/List_of_object-relational_mapping_software . Cred ca ar trebui sa cititi cel putin unul, de exemplu Nhibernate : http://www.hibernate.org/343.html
Pentru a genera acelasi cod plecind de la tabele dintr-o baza de date, cititi Code Generation (http://en.wikipedia.org/wiki/Code_generation) si poate CodeSmith (http://www.codesmithtools.com/)
Programming in .NET - partea a 2-a - creearea Bazei de date Cititi mai intii <a href="http://serviciipeweb.ro/iafblog/2006/08/10/Programarea+In+NET+Partea+1.aspx">Programarea In NET - Partea 1 </a> Conventie : notarile si codul si comentariile or sa fie in engleza. Nu de alta -dar e limba internationala a programarii. Bun - acum ca ne-am lamurit ce vrem sa facem, hai sa concepem Baza de date. Aceasta o sa fie, pentru Windows forms, Access - iar pentru ASP.NET - SQL Express. De ce aceasta alegere ? Simplu : Pentru aplicatia Windows forms - aleg ceva care sa fie usor de facut deployment-ul Pentru aplicatia ASP.NET - trebuie sa fie ceva care sa mearga repede - deci un SQL Server se impune Cum o sa facem sa generam cod pentru oricare din acestea doua, o sa vedeti. Structura Proiectului: O sa cream proiectul in C:\Book In acest director vom crea BookWin.sln ( solutia care va tine proeictul windows si proiectul Consola dos) si BookWeb.sln (solutia care va contine proiectul Web -si aplicatia SmartClient) In acest director vom avea: BookData( fisierele mdb, scripturile de creeare sql express) BookObjects( proiectul de conectare la BD si de obiecte) BookWin( proiectul de Windows) BookDos ( proiectul de DOS) BookWeb(proiectul Web) BookDeployWeb(proiectul de deployment Web) BookDeployWin(proiectul de deployment Windows) BookDeploySmartClient(unde vom face deployment-ul SmartClient) BookTest Bun - acum haideti sa facem primul pas - creearea bazei de date Access. Haideti sa creeam impreuna MDB-ul. Pornim Acces - cream o noua baza de date - o salvam in BookData. O sa va arat cum se creeaza prima tabela: Cind sunteti pe tabul "Tables" apasati pe "New Table"
Alegeti "Design View"
Si incepeti sa introduceti valorile prezentate
Pentru a face IDAuthor Primary Key - dati click dreapta pe coloana de dinainte de IDAuthor si click pe "Primary Key"
La fel se creeaza si celelalte tabele. Acum ar trebui sa le legam intre ele. Pentru aceasta , accesati Tools=> Relationships Adaugati tabelele
Trageti , de pilda, de la IDBook de la tabela Book la IDBook de la tabela Author_Book
Aveti grija sa selectati "referential entigrity" - cascade delete si update
Acum avem Baza de date.Il puteti downloada de aici: book.mdb Haideti sa concepem obiectele.Acestea or sa fie ca in prima prezentare: <a href="http://serviciipeweb.ro/iafblog/2006/08/10/Programarea+In+NET+Partea+1.aspx">Programarea In NET - Partea 1 </a> In a treia parte, postata online la data de 28 August 2006 o sa scriem cod pentru accesul la Baza de date, precum si obiectele principale pentru acest proiect.
Theme design by Jelle Druyts
Pick a theme: BlogXP business calmBlue Candid Blue dasBlog dasblogger DirectionalRedux Discreet Blog Blue Elegante essence Just Html Mono Movable Radio Blue Movable Radio Heat orangeCream Portal Project84 Project84Grass Slate Tricoleur