środa, 3 marca 2010

Tworzenie web serwisu WCF cz. 3

W tej części kursu zajmiemy się "konsumpcją" stworzonego przez nas wcześniej serwisu opartego o WCF. Jak wcześniej wspominałem, stworzyliśmy WCF Library Application co daje nam spore możliwości odnośnie wykorzystania naszego web serwisu. Tutaj, postaram się w miarę jasno pokazać jak użyć naszej aplikacji do stworzenia prostej aplikacji ASP.NET i WinForms.

ASP.NET
Zaczniemy od aplikacji webowej. 
1. Otwieramy stworzony przez nas ostatnio projekt, klikamy prawym przyciskiem myszy i wybieramy Add New Project...
2. Wybieramy ASP.NET Web Application, nadajemy nazwę i klikamy Ok. Po zatwierdzeniu powinniśmy otrzymać taki widok naszych projektów:


Aplikację podzieliłem na 3 oddzielne podstrony:

Pierwsza będzie odpowiedzialna za dodanie nowego klienta do bazy danych. Druga pozwoli na wyświetlenie klienta o określonym Id. Ostatnia wyświetli wszystkich klientów w bazie. A więc do dzieła :)


3. Usuwamy z naszego projektu plik Default.aspx i dodajemy nowy plik: MasterPage.Master. Pozwoli nam to na stworzenie menu, które będzie na każdej podstronie naszego serwisu, bez konieczności kopiowania na wszystkie podstrony kodu odpowiedzialnego za menu.
4. Do utworzonego MasterPaga dodajemy prostą tabelkę z jednym wierszem i dwiema komórkami:


<%@ Master Language="C#" AutoEventWireup="true"  
CodeBehind="MasterPage.master.cs" Inherits="
WebPage.MasterPage" %>
 
<!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></title>
    <asp:ContentPlaceHolder ID="head" runat="server">
    </asp:ContentPlaceHolder>
</head>
<body>
    <form id="form1" runat="server">
    <table border="2" cellpadding="10">
    <tr align="left" valign="top">
    <!--Menu naszej strony -->
    <td>
        <asp:HyperLink ID="HyperLink1" runat=
"server">Add new customer</asp:HyperLink>
        <br />
        <asp:HyperLink ID="HyperLink2" runat=
"server">Customer information</asp:HyperLink>
        <br />
        <asp:HyperLink ID="HyperLink3" runat=
"server">Show all customer</asp:HyperLink>
    </td>
    <!-- Zawartość strony -->
    <td>
    <asp:ContentPlaceHolder runat="server"  
ID="contetnPlaceHolder"></asp:ContentPlaceHolder>
    </td>
    </tr>
    </table>
    </form>
</body>
</html>
 
Pierwsza komórka zawiera proste menu, druga resztę zawartości.
5. Dodajemy nowy plik do projektu typu WebContent Form. Po nadaniu nazwy pojawi się okienko w którym wybieramy nasz MasterPage i akceptujemy wybór.
6. Do ContentPlaceHoldera dodajemy po dwie kontrolki Label i TextBox oraz jeden przycik:

<%@ Page Title="" Language="C#" MasterPageFile=
"~/MasterPage.Master" AutoEventWireup="true" 
CodeBehind="AddNewCustomer.aspx.cs" Inherits=
"WebPage.AddNewCustomer" %>
<asp:Content ID="Content1" ContentPlaceHolderID=
"head" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID=
"contetnPlaceHolder" runat="server">
    <asp:Label ID="Label1" runat="server" Text=
"Imię: "></asp:Label>
    <asp:TextBox runat="server" ID="tbFistName">
</asp:TextBox>
    <br />
    <br />
    <asp:Label runat="server" ID="Label2" Text=
"Nazwisko"></asp:Label>
    <asp:TextBox runat="server" ID="tbLastName">
</asp:TextBox>
    <br />
    <br />
    <asp:Button runat="server" ID="Submit" Text="Wyślij"/>
</asp:Content>

7. Następnie dodajemy dwie kolejne podstrony: CustomerInfo i AllCustomers tak jak w poprzednim kroku:
CustomerInfo:

<%@ Page Title="" Language="C#" MasterPageFile=
"~/MasterPage.Master" AutoEventWireup="true" 
CodeBehind="CustomerInfo.aspx.cs" Inherits=
"WebPage.CustomerInfo" %>
<asp:Content ID="Content1" ContentPlaceHolderID=
"head" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID=
"contetnPlaceHolder" runat="server">
    <asp:Label ID="Label1" runat="server" Text="Id: ">
</asp:Label>
&nbsp;<asp:TextBox ID="TextBox1" runat="server" 
        ontextchanged="TextBox1_TextChanged">
</asp:TextBox>
    <br />
    <asp:Button ID="BShow" runat="server"  
Text="Pokaż" />
    <br />
    <asp:Label ID="LId" runat="server"></asp:Label>
    <br />
    <asp:Label ID="LFirstName" runat="server">
</asp:Label>
    <br />
    <asp:Label ID="LLastName" runat="server">
</asp:Label>
    <br />
</asp:Content>
 
AllCustomers:

<%@ Page Title="" Language="C#" MasterPageFile=
"~/MasterPage.Master" AutoEventWireup="true"  
CodeBehind="AllCustomers.aspx.cs" Inherits=
"WebPage.AllCustomers" %>
<asp:Content ID="Content1" ContentPlaceHolderID=
"head" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID=
"contetnPlaceHolder" runat="server">
    <asp:GridView ID="GridView1" runat="server">
    </asp:GridView>
</asp:Content>
8. Kolejnym krokiem jest dodanie referencji do naszego web serwisu. Klikamy prawym klawiszem na naszym projekcie ASP.NET i wybieramy opcje Add Service Reference. Pojawi się nowe okienko w którym klikamy na przycisk Discover. Po tej czynności powinniśmy ujrzeć następujący ekran:

Wprowadzamy wartość Namespace np. MyService i akceptujemy. Do naszego projektu zostanie dodana tzw. klasa Proxy która zajmie się zarządzaniem przesyłania danych pomiędzy web serwisem a naszą aplikacją. 
9. Przechodzimy do naszej pierwszej podstrony, dotyczącej dodawania nowego użytkownika i dodajemy nowe zdarzenie do przycisku Wyślij:

        protected void Submit_Click(object sender, 
EventArgs e)
        {
            MyService.Customer cust = 
new WebPage.MyService.Customer();
            cust.FirstName = tbFistName.Text;
            cust._lastName = tbLastName.Text;
            MyService.CustomerServiceClient client = 
new WebPage.MyService.CustomerServiceClient();
            client.AddNewCustomer(cust);
        }
 
Następnie kod przycisku pokaż dla strony CustomerInfo:

        protected void BShow_Click(object sender,  
EventArgs e)
        {
            MyService.CustomerServiceClient client = 
new WebPage.MyService.CustomerServiceClient();
            MyService.Customer c = 
client.GetCustomerById(int.Parse(tbId.Text));
            LFirstName.Text = c.FirstName;
            LLastName.Text = c._lastName;
            LId.Text = c.ID.ToString();
        }
 
Oraz kod wyświetlający wszystkich klientów:

        protected void Page_Load(object sender,  
EventArgs e)
        {
            MyService.CustomerServiceClient client = 
new WebPage.MyService.CustomerServiceClient();
            GridView1.DataSource = 
client.GetAllCustomers();
            GridView1.DataBind();
        }

9. Jeśli dodaliśmy już potrzebny kod czas na przetestowanie naszej aplikacji. Odpalamy nasz projekt i próbujemy dodać nową osobę. Po przeładowaniu strony, jeśli wcześniej nie pojawi się żaden błąd, nowa osoba zostanie dodana do bazy. Także podczas pobierania informacji o nowej osobie nie powinniśmy mieć żadnych problemów:

10. Przejdźmy do wyświetlenia informacji o wszystkich  klientach. Klikamy na Show all customer i otrzymujemy piękny błąd:


Błąd jest spowodowany tym, że domyślnie nasz web serwis ma ustawione aby maksymalna paczka przesyłana do naszej aplikacji miała 64kb. Ponieważ w bazie jest duża ilość klientów, 64kb to trochę za mało aby ich wszystkich na raz przesłać. Istnieje kilka sposób na poradzenie sobie z tym problemem:
1. CustomPaging w GridView i pobieranie tylko wierszy o wskazanym Id
2. Zwiększenie maksymalnej wielkości przesyłanej od serwisu do naszej aplikacji.
 Tutaj opiszę 2 możliwość, gdyż jest bezpośrednio związana z naszym web serwisem.

Klikamy prawym klawiszem na App.Config w web serwisie i wybieramy EditWCF configuration...
Przechodzimy do części Bindings, wybieramy New Binding Configuration...
Z listy wybieramy pasujący do naszego punktu końcowego format (wsHttpBinding) 
Edytujemy kolejno wartości: MaxBufferPoolSize oraz MaxRecivedMessageSize. Zwiększymy obie wartości do np. 10 MB: 10485760:


Teraz dopisujemy konfigurację do naszego punktu końcowego:


Po tym zabiegu nasz serwis nadal nie będzie działać jeszcze poprawnie. Dzieje się tak dlatego, że wielkość paczki należy ustawić po obu stronach: klienta i serwera. Po stronie serwera mamy już sprawę załatwioną. Czas na klienta:
Tak jak poprzednio klikamy prawym klawiszem myszki na Web.Config i edytujemy właściwości WCF. Tutaj już jednak w Bindingu mamy na gotowe plik konfiguracyjny. Wystarczy tylko zwiększyć poprzednio pokazane wartości. Po zaakceptowaniu zmian możemy uruchomić ponownie nasz projekt.
Po ponownym odpaleniu projektu i wybraniu podstrony wyświetlającej wszystkich klientów otrzymamy ich całą listę:
Tak więc cel został osiągnięty :)


WinForms
1. Do projektu dodajemy nowy projekt WindowsForms.
2. Dodajemy TabControl do formatki: 
3. Dodajemy kontrolki do każdej zakładki oraz referencję do serwisu:
4.  Teraz do każdego przycisku odpowiedni kod (analogicznie jak dla wersji ASP.NET)
5. Zmieniamy wielkość przesyłanych danych do 10 MB po stronie klienta (plik app.config)
6. Kompilujemy i odpalamy naszą aplikację:

 Jak widać tworzenie serwisów w WCF nie jest skomplikowane a niesie za sobą wiele korzyści. WCF jest bardzo elastyczną technologią i skazaną na swój rynkowy sukces.

poniedziałek, 1 marca 2010

Tworzenie web serwisu WCF cz. 2

W poprzedniej części omawialiśmy tematykę tworzenia web serwisu od podstaw. Dzisiaj zajmiemy się tematyką testowania stworzonej przez nas biblioteki. VS 2008 zawiera bardzo pomocny dodatek, który pomaga testować większość kodu zapisanego w utworzonym przez nas web serwisie. 
Otwieramy więc tworzony przez nas ostatnio projekt i klikami F5. Czekamy teraz na otwarcie się poniższego okna: 
Większość z was z pewnością zwróciła uwagę na czerwony wykrzyknik przy metodzie GetAllCustomers(). Nie oznacza to, że napisaliśmy błędnie metodę a jedynie to, że narzędzie do testowania nie jest jej w stanie obsłużyć. Tak więc pozostają nam pozostałe dwie metody do testu. Otwórzmy dwuklikiem GetCustomerById(). Stworzy nam to nową zakładkę na której możemy skonfigurować wartości służące do wysłania zapytania:
Jak wcześniej omawialiśmy metoda GetCustomerById() pobiera informacje o konkretnym kliencie wskazanym poprzez jego ID. Po wprowadzeniu Id klikamy na przycisk Invoke i czekamy na rezultat (lub błąd :) ):
Jak więc widać nasze zapytanie zadziałało i wyprowadziło prawidłowy rezultat. Spróbujmy teraz wykonać podobne operacje dla metody AddNewCustomer(). Tak jak poprzednio wprowadzamy dane i oczekujemy na rezultat:
Tutaj małe sprostowanie. Id nie wprowadzam gdyż w bazie pole to jest domyślnie oznaczone jako Identity, czyli w skrócie autoinkrementacja.

Niestety ostatniej metody nie przetestujemy. Będzie z nią także mały problem podczas konsumpcji web serwisu ale o tym w następnej części :)

niedziela, 28 lutego 2010

Tworzenie webserwisu WCF cz. 1


Dzisiaj coś łatwego – stworzenie prostego web serwisu WCF i jego konsumpcja za pomocą aplikacji ASP.NET. 
Całość została podzielona na 3 części: 
1. (ta którą obecnie drogi czytelniku oglądasz) obejmuje tematyką tworzenie aplikacji WCF
2. Opisuje testowanie aplikacji WCF
3. Pokazuje w jaki sposób za pomocą ASP.NET "skonsumować" aplikację WCF
Nasz web serwis będzie umożliwiał wyświetlenie wszystkich naszych klientów, wybranego klienta oraz pozwoli dodawać nowych klientów.
Dla przykładu posłużę się bazą danych AdventureWorksLT2008 działającą pod kontrolą SQL Server 2008. Kroki, które należy wykonać aby utworzyć WebService:
1. Uruchamiamy Visual Studio 2008 i tworzymy nowy projekt: WCF Service Library
Warto tutaj zauważyć, że w szablonach VS mamy do wyboru WCF Service Application. Nie zalecam jego używania, gdyż ma ograniczone możliwości. W przypadku biblioteki otrzymujemy komponent który możemy następnie jako web serwis, usługę systemu Windows itp. Z kolei WCF Service Application oferuje nam podobne możliwości co web serwisy na platformie ASP.NET.
2. Usuwamy pliki Iservice1.cs i Service1.svc (stworzymy całość od 0)
3. Dodajemy nową klasę do naszego projektu:


    [DataContract]
    public class Customer
    {
        private int _id;
        [DataMember]
        public int ID
        {
            get
            {
                return _id;
            }
            set
            {
                _id = value;
            }
        }
 
        private string _firstName;
        [DataMember]
        public string FirstName
        {
            get
            {
                return _firstName;
            }
            set
            {
                _firstName = value;
            }
        }
        [DataMember]
        private string _lastName;
        public string LastName
        {
            set
            {
                _lastName = value;
            }
            get
            {
                return _lastName;
            }
 
        }
    }
}
Atrybut DataContract pozwala na utworzenie kontraktu dzięki któremu nastąpi serializacja do XMLa. Poprzez atrybuty DataMember określamy które pola mają zostać zserializowane.
4. Dodajemy do naszego projektu interfejs:




    [ServiceContract]
    public interface ICustomerService
    {
        [OperationContract]
        void AddNewCustomer(Customer customer);
        [OperationContract]
        Customer GetCustomerById(int id);
        [OperationContract]
        DataTable GetAllCustomers();
    }


ICustomerService definiuje jakie operacje będą widoczne na zewnątrz (czyli z jakich metod będzie mógł korzystać użytkownik naszej aplikacji). Znacznikiem [ServiceContract] oznaczamy klasę/strukturę lub interfejs który zamierzamy udostępnić a znacznikami OperationContract oznaczamy które metody będą eksponowane.
5. Przechodzimy do części odpowiedzialnej za obsługę connectionStringów i dodajemy odpowiedni dla naszej bazy danych:

<add name="AdventureWorks" providerName="System.Data.SqlClient"  
connectionString="Data Source=.\sqlexpress;Initial Catalog=
AdventureWorksLT2008;Integrated Security=True"/>

6. Dodajemy kolejną klasę, która będzie implementowała nasz interfejs:







    [ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
    class CustomerService : ICustomerService
    {
        private string providerName = ConfigurationManager.
ConnectionStrings["AdventureWorks"].ProviderName;
        private string connectionString = ConfigurationManager.
ConnectionStrings["AdventureWorks"].ConnectionString;
        #region ICustomerService Members
 
        public void AddNewCustomer(Customer customer)
        {
            DbProviderFactory dbFactory = DbProviderFactories.GetFactory
(providerName);
            DbConnection conn = dbFactory.CreateConnection();
            conn.ConnectionString = connectionString;
            DbCommand cmd = conn.CreateCommand();
            try
            {
                cmd.CommandText = "INSERT INTO SalesLT.Customer(FirstName, 
LastName) VALUES(@firstName, @lastName)";
                conn.Open();
                DbParameter parameter = dbFactory.CreateParameter();
                parameter.DbType = DbType.AnsiString;
                parameter.Value = customer.FirstName;
                parameter.ParameterName = "firstName";
                cmd.Parameters.Add(parameter);
                parameter = dbFactory.CreateParameter();
                parameter.DbType = DbType.AnsiString;
                parameter.Value = customer.LastName;
                parameter.ParameterName = "lastName";
                cmd.Parameters.Add(parameter);
                cmd.ExecuteNonQuery();
                conn.Close();
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
 
        public Customer GetCustomerById(int id)
        {
            DbProviderFactory dbFactory = DbProviderFactories.GetFactory
(providerName);
            DbConnection conn = dbFactory.CreateConnection();
            conn.ConnectionString = connectionString;
            conn.ConnectionString = connectionString;
            DbCommand cmd = conn.CreateCommand();
            try
            {
                cmd.CommandText = "select FirstName, LastName from SalesLT.
Customer where CustomerID = @custId";
                DbParameter parameter = dbFactory.CreateParameter();
                parameter.DbType = DbType.Int32;
                parameter.Value = id;
                parameter.ParameterName = "custId";
                cmd.Parameters.Add(parameter);
 
                DbDataAdapter da = dbFactory.CreateDataAdapter();
                da.SelectCommand = cmd;
                DataSet ds = new DataSet();
                da.Fill(ds);
                Customer c = new Customer();
                c.ID = id;
                c.FirstName = ds.Tables[0].Rows[0]["FirstName"].ToString();
                c.LastName = ds.Tables[0].Rows[0]["LastName"].ToString();
                return c;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
 
        public System.Data.DataTable GetAllCustomers()
        {
            DbProviderFactory dbFactory = DbProviderFactories.GetFactory
(providerName);
            DbConnection conn = dbFactory.CreateConnection();
            conn.ConnectionString = connectionString;
            DbCommand cmd = conn.CreateCommand();
            try
            {
                cmd.CommandText = "select FirstName, LastName from SalesLT.
Customer";
                conn.Open();
                DbDataAdapter da = dbFactory.CreateDataAdapter();
                da.SelectCommand = cmd;
                DataSet ds = new DataSet();
                da.Fill(ds);
                conn.Close();
                return ds.Tables[0];
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
 
        #endregion
    }
Metody działają tak jak są opisane. AddNewCustomer dodaje nowego klienta, 
GetCustomerById powoduje zwrócenie imienia i nazwiska klienta o określonym Id. 
GetCustomers zwraca wszystkich klientów. 

7. Przechodzimy do modyfikacji ustawień naszego serwisu klikamy prawym klawiszem 
myszy na plik App.config i wybieramy Edit WCF Configuration. Po wybraniu tej 
opcji powinniśmy ujrzeć następujący ekran:
 
 
Pierwsze co rzuca się w oczy to niewłaściwa nazwa naszego serwisu. Aby zmienić ją na 
poprawną (AdventureWorks) wchodzimy w kolejno Services -> AdventureWorks.Service1 -> 
właściwość name. Po kliknięciu na klawisz wyboru  przechodzimy kolejno do: bin -> 
Debug -> AdventureWorks.dll -> AdventureWorks.CustomerService po kliknięciu na 
open nazwa serwisu się zmieni na prawidłową.
 
Następnie modyfikujemy punkty końcowe naszego serwisu:
 
Przechodzimy tak jak poprzednio przez wszystkie foldery i wybieramy: 
AdentureWorks.ICustomerService

Drugi punkt końcowy służy do pobierania metadanych podczas działania naszego 
serwisu. Tak więc zostawiamy wartości drugiego punktu końcowego nietknięte.  

sobota, 20 lutego 2010

WPF w praktyce


Kilka praktycznych porad dal osób dopiero zaczynających przygodę z WPF.

1. Kontrolka RichTextBox
a) pobieranie zawartości kontrolki
Jeśli ktoś korzystał wcześniej z WindowsForms i pobranie zawartości tekstu znajdującego się wewnątrz kontrolki RichTextBox nie sprawiało mu problemów (właściwość Text) to w przypadku WPF może nie być już to takie jasne.
WPF wykorzystuje nowy model "zawartości" i aby pobrać text z naszej kontrolki możemy skorzystać z poniższego kodu:

TextRange textRange = new TextRange(rtb.Document.ContentStart, rtb.Document.ContentEnd);
string s = textRange.Text;
 
b) programowe dodawanie tekstu
Także dodawanie tekstu "z kodu" nie jest takie oczywiste jak w WindowsForms:
 
            FlowDocument flowDocument = new FlowDocument();
            Paragraph para = new Paragraph();
            para.Inlines.Add("Text to add");
            flowDocument.Blocks.Add(para);
            rtb.Document = flowDocument;
Jak więc widać, aby dodać tekst należy najpierw stworzyć obiekt klasy FlowDocument oraz Paragraph. Następnie do kolekcji Inlines Paragraphu dodajemy tekst który chcemy ujrzeć w kontrolce. Na końcu do kolekcji Blocks FlowDocumentu dodajemy nasz paragraf i ostatecznie przypisujemy właściwości Document RichTextBoxa obiekt FlowDocument.

c) wczytywanie danych z pliku
Jak się domyślacie także i ta sprawa nie jest od początku taka oczywista :). W WinForms kontrolka posiadała wygodną metodę LoadFile() która pozwalała określić np. ścieżkę z której można załadować plik. W WPF należy skorzystać bezpośrednio ze strumienia:
 
            System.Windows.Forms.OpenFileDialog ofd = new System.Windows.Forms.OpenFileDialog();
            ofd.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            ofd.Filter = "Plik textowy (*.txt)|*.txt";
            ofd.RestoreDirectory = true;
            if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                string fileName = ofd.FileName;
                TextRange textRange = new TextRange(rtbToChange.Document.ContentStart, rtbToChange.Document.ContentEnd);
                System.IO.FileStream fs = new System.IO.FileStream(fileName, System.IO.FileMode.Open);
                textRange.Load(fs, System.Windows.DataFormats.Text);
                fs.Close();
            }
Skorzystałem tutaj z wygodnego (jak mi się wydaje) OpenFileDialoga znajdującego się w Windows.Forms (można także tutaj skorzystać z OpenFileDialog znajdującego się w System.Win32). Następnie postępujemy jak przy obsłudze większości plików:
1. Otwieramy plik
2. Tworzymy obiekt TextRange któremu przekazujemy granice dokumentu
3. Korzystamy z metody Load(IO.Stream, dataFormat) która wczytuje tekst do RichTextBoxa ze strumienia
4. Po zakończeniu pracy z plikiem zamykamy go.

2. Button
Problem także nie ominął mnie także w kwestii zwykłego przycisku. Znana właściwość z WinForms FlatStyle: Flat, nie występuje w WPFowskiej kontrolce Button. Aby nadać płaski styl przyciskowi można użyć poniżeszego kodu:

Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}

Powyższą linijkę wstawiamy bezpośrednio do kodu XAML podczas deklaracji Buttona.

Podsumowując:
WPF przez swoją innowacyjność wymaga poznania nowych mechanizmów, które niekiedy ułatwiają a niekiedy utrudniają pracę programiście :)

niedziela, 14 lutego 2010

O ConnectionString słów kilka…


Każdy z pewnością miał do czynienia z tworzeniem oprogramowania operującego na bazie danych(DB). Każdy też ma swój sposób na interakcję i łączenie się z DB. Należałoby się jednak zastanowić, czy stosowane techniki pozwalają w łatwy sposób na zmianę rodzaju bazy danych? Przeważnie podczas tworzenia nowego połączenia z bazą danych na stałe używamy jednego providera:
            string connectionString = @"Data Source=.\sqlexpress;Initial Catalog=AdventureWorksLT2008;Integrated Security=True";
            DbConnection conn = new SqlConnection(connectionString);
            DbCommand cmd = conn.CreateCommand();
            cmd.CommandText = "SELECT firstname FROM customers";
            conn.Open();
            //instrukcje
            conn.Close();

Sposób powyższy ma przynajmniej dwie wady:
1. "hard code" (spolszczyłbym to na: "stałe") zakodowanie providera;
2. Brak możliwości zmiany bazy danych (np. Oracle używa innego providera) bez zbędnych modyfikacji całego kodu;

Jak widać co jest oczywiste nie zawsze jest idealne. .NET Framework dostarcza nam (zarówno dla aplikacji ASP.NET jak i WinForms czy WPF) plik pozwalający na zapis naszych ConnectionString. 
Aby skorzystać z tego dobrodziejstwa dodajemy do naszego projektu plik Appliaction Configuration File:
Po dodaniu go do projektu powinien się od razu otworzyć z zawartością:


<?xml version="1.0" encoding="utf-8" ?>
<configuration>
</configuration>
 
Pomiędzy znaczniki <configuration></configuration> możemy wprowadzić m.in. nasze ConnectionString:
 
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <connectionStrings>
    <add/>
  </connectionStrings>
</configuration>
 
Za pomocą komendy <add/> dodajemy nowy ConnectionString. Znacznik ten składa się z 3 ważnych atrybutów: 
 
name  - przyjazna nazwa
connectionString - właściwy ConnectionString
providerName - nazwa providera
 
Przykład:
  

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <connectionStrings>
    <add name="AdventureWorks" providerName="System.Data.SqlClient" connectionString="Data Source=.\sqlexpress;Initial Catalog=AdventureWorksLT2008;Integrated Security=True;"/>
  </connectionStrings>
</configuration>
 
Aby odwołać się w kodzie do podanego ConnectionString-a o nazwie AdventureWorks, wystarczy najpierw dodać referencję do biblioteki System.Configuration:
 
 Teraz w miejscu gdzie chcemy utworzyć połączenie:
 
            string connectionString = ConfigurationManager.ConnectionStrings["AdventureWorks"].ConnectionString;
            DbProviderFactory factory = DbProviderFactories.GetFactory(ConfigurationManager.ConnectionStrings["AdventureWorks"].ProviderName);
            DbConnection conn = factory.CreateConnection();
            conn.ConnectionString = connectionString;
            DbCommand cmd = conn.CreateCommand();
            cmd.CommandText = "SELECT firstname FROM customers";
            conn.Open();
            //instrukcje
            conn.Close();

Korzystamy tutaj z klasy DbProviderFactories, która tworzy odpowiedni provider na podstawie jego nazwy. Dzięki temu w jednym pliku możemy złożyć wszystkie ConnectionStrings. W razie potrzeby zmiana będzie wymagana jedynie w tym jednym pliku a nie w całym programie.

Jeżeli chodzi o aplikacje ASP.NET, sprawa jest jeszcze łatwiejsza. W pliku Web.config dodajemy wpis w miejscu przeznaczonym na ConnectionStrings i już możemy z niego korzystać tak samo jak w aplikacjach desktopowych :)