2009-04-29 13 views
7

मैंने अभी सी # में प्रोग्रामिंग शुरू की है और तीन अलग-अलग परतों में अपने एप्लिकेशन/वेबसाइट को विभाजित करने के बारे में पढ़ना सबसे अच्छा अभ्यास था, लेकिन मुझे वास्तव में समझने में कठिनाई हो रही है। मैं सी # के बारे में अधिक जानकारी देने के लिए एक पालतू परियोजना पर काम कर रहा हूं लेकिन मैं किसी भी बुरी आदतों पर शुरू नहीं करना चाहता हूं। क्या आप देख सकते हैं कि मेरे पास क्या है और देखें कि क्या मैं यह सही कर रहा हूं? विभिन्न संकेतों को सब कुछ तोड़ने के तरीके के बारे में कुछ संकेत दें।प्रेजेंटेशन, बिजनेस और डेटा लेयर

प्रस्तुति परत

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> 

<!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>Project: Ruth</title> 
    <link href="CSS/StyleSheet.css" rel="stylesheet" type="text/css" /> 
</head> 
<body> 
    <form id="form1" runat="server"> 
    <div class="Body"> 
     <div class="Header"> 
     <div class="Nav"> 
      <img src="images/Header_Main.gif" alt="" width="217" height="101" /> 
      <div class="Menu"> 
      <a href="Default.aspx"> 
       <img src="images/Header_Home-Off.gif" alt="" /></a> 
      <a href="Default.aspx"> 
       <img src="images/Header_About-Off.gif" alt="" /></a> 
      <a href="Register.aspx"> 
       <img src="images/Header_Register-Off.gif" alt="" /></a> 
      <a href="Default.aspx"> 
       <img src="images/Header_Credits-Off.gif" alt="" /></a> 
      </div> 
     </div> 
     </div> 
     <div class="Content"> 
     <div class="CurrentlyListening"> 
      <asp:Label ID="lblCurrentListen" runat="server" Text="(Nothing Now)" CssClass="Txt"></asp:Label> 
     </div> 
     <asp:GridView ID="gvLibrary" runat="server" AutoGenerateColumns="False" DataKeyNames="lib_id" DataSourceID="sdsLibrary" EmptyDataText="There are no data records to display." Width="760" GridLines="None"> 
      <RowStyle CssClass="RowStyle" /> 
      <AlternatingRowStyle CssClass="AltRowStyle" /> 
      <HeaderStyle CssClass="HeaderStyle" /> 
      <Columns> 
      <asp:BoundField DataField="artist_name" HeaderText="Artist" SortExpression="artist_name" HeaderStyle-Width="200" /> 
      <asp:BoundField DataField="album_title" HeaderText="Album" SortExpression="album_title" HeaderStyle-Width="200" /> 
      <asp:BoundField DataField="song_title" HeaderText="Track" SortExpression="song_title" HeaderStyle-Width="200" /> 
      <asp:TemplateField HeaderText="DL"> 
       <ItemTemplate> 
       <a href="http://####/Proj_Ruth/Data/<%# Eval("file_path") %>" class="lnk">Link</a> 
       </ItemTemplate> 
      </asp:TemplateField> 
      </Columns> 
     </asp:GridView> 
     <asp:SqlDataSource ID="sdsLibrary" runat="server" ConnectionString="<%$ ConnectionStrings:MusicLibraryConnectionString %>" DeleteCommand="DELETE FROM [Library] WHERE [lib_id] = @lib_id" InsertCommand="INSERT INTO [Library] ([artist_name], [album_title], [song_title], [file_path]) VALUES (@artist_name, @album_title, @song_title, @file_path)" ProviderName="<%$ ConnectionStrings:MusicLibraryConnectionString.ProviderName %>" SelectCommand="SELECT [lib_id], [artist_name], [album_title], [song_title], [file_path] FROM [Library] ORDER BY [artist_name], [album_title]" UpdateCommand="UPDATE [Library] SET [artist_name] = @artist_name, [album_title] = @album_title, [song_title] = @song_title, [file_path] = @file_path WHERE [lib_id] = @lib_id"> 
      <DeleteParameters> 
      <asp:Parameter Name="lib_id" Type="Int32" /> 
      </DeleteParameters> 
      <InsertParameters> 
      <asp:Parameter Name="artist_name" Type="String" /> 
      <asp:Parameter Name="album_title" Type="String" /> 
      <asp:Parameter Name="song_title" Type="String" /> 
      <asp:Parameter Name="file_path" Type="String" /> 
      </InsertParameters> 
      <UpdateParameters> 
      <asp:Parameter Name="artist_name" Type="String" /> 
      <asp:Parameter Name="album_title" Type="String" /> 
      <asp:Parameter Name="song_title" Type="String" /> 
      <asp:Parameter Name="file_path" Type="String" /> 
      <asp:Parameter Name="lib_id" Type="Int32" /> 
      </UpdateParameters> 
     </asp:SqlDataSource> 
     </div> 
    </div> 
    </form> 
</body> 
</html> 

व्यापार लेयर

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 

public class User 
{ 
    DA da = new DA(); 

    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public string EmailAddress { get; set; } 
    public string Password { get; set; } 
    public string AccessCode { get; set; } 

    public User(string firstName, string lastName, string emailAddress, string password, string accessCode) 
    { 
    FirstName = firstName; 
    LastName = lastName; 
    EmailAddress = emailAddress; 
    Password = password; 
    AccessCode = accessCode; 
    } 

    public void CreateUser(User newUser) 
    { 
    if (da.IsValidAccessCode(newUser.AccessCode)) 
    { 
     da.CreateUser(newUser); 
    } 
    } 
} 

डेटा एक्सेस लेयर (दाल)

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Data; 
using System.Data.SqlTypes; 
using System.Data.SqlClient; 
using System.Configuration; 

public class DA 
{ 
    public DA() 
    { 
    } 

    public bool IsValidAccessCode(string accessCode) 
    { 
    bool isValid = false; 
    int count = 0; 

    using (SqlConnection sqlCnn = new SqlConnection(ConfigurationManager.ConnectionStrings["MusicLibraryConnectionString"].ConnectionString)) 
    { 
     sqlCnn.Open(); 
     using (SqlCommand sqlCmd = new SqlCommand(String.Format("SELECT COUNT(*) FROM [AccessCodes] WHERE [accessCode_accessCode] = '{0}';", accessCode), sqlCnn)) 
     { 
     count = (int)sqlCmd.ExecuteScalar(); 
     if (count == 1) 
     { 
      isValid = true; 
     } 
     } 
    } 
    return isValid; 
    } 

    public void CreateUser(User newUser) 
    { 
    using (SqlConnection sqlCnn = new SqlConnection(ConfigurationManager.ConnectionStrings["MusicLibraryConnectionString"].ConnectionString)) 
    { 
     sqlCnn.Open(); 
     using (SqlCommand sqlCmd = new SqlCommand(String.Format("INSERT INTO [Users] (user_firstName, user_lastName, user_emailAddress, user_password, user_accessCode) VALUES ('{0}', '{1}', '{2}', '{3}', '{4}');", newUser.FirstName, newUser.LastName, newUser.EmailAddress, newUser.Password, newUser.AccessCode), sqlCnn)) 
     { 
     sqlCmd.ExecuteNonQuery(); 
     } 
    } 
    DeleteAccessCode(newUser.AccessCode); 
    } 

    public void DeleteAccessCode(string accessCode) 
    { 
    using (SqlConnection sqlCnn = new SqlConnection(ConfigurationManager.ConnectionStrings["MusicLibraryConnectionString"].ConnectionString)) 
    { 
     sqlCnn.Open(); 
     using (SqlCommand sqlCmd = new SqlCommand(String.Format("DELETE FROM [AccessCodes] WHERE [accessCode_accessCode] = '{0}';", accessCode), sqlCnn)) 
     { 
     sqlCmd.ExecuteNonQuery(); 
     } 
    } 
    } 
} 

उत्तर

9

जॉन,

पहले चीजों को समझने के लिए यह है कि यदि आप परत-आधारित अनुप्रयोगों का निर्माण करना चाहते हैं, तो आप नहीं SQL कथन ASPX पृष्ठों के भीतर सीधे भंडारण किया जाना चाहिए (के रूप में SqlDataSource की आवश्यकता है) है। SqlDataSource नियंत्रण यह प्रदर्शित करने के लिए बनाया गया था कि डेटाबेस डेटा के साथ किसी एप्लिकेशन को बाध्य करना और अपडेट करना कितना आसान है और वास्तविक दुनिया अनुप्रयोगों में इसका उपयोग करने का इरादा नहीं है, क्योंकि अगर आप बीएल परत और डातालियर होने के उद्देश्य को हराते हैं तो आप इसे खो देते हैं एएसपीएक्स पेज में स्टोर का चयन/अद्यतन/हटाएं/कथन डालें।

परत-आधारित अनुप्रयोग डिज़ाइन का पूरा उद्देश्य प्रत्येक परत को समाहित करना है ताकि कोई छेड़छाड़ न हो। प्रत्येक परत अन्य परतों के सार्वजनिक इंटरफेस के साथ बातचीत करती है और उनके आंतरिक कार्यान्वयन के बारे में कुछ भी नहीं जानता है।

व्यवहार्य विकल्प, इसलिए ObjectDataSource नियंत्रण का उपयोग करना है। यह नियंत्रण आपको सीधे डेटालेयर या बिज़ लॉजिक लेयर से जुड़ने की अनुमति देता है जो बदले में डाटालेयर को कॉल कर सकता है। एक डातालियर को बाध्यकारी सीधे दोष है कि आप डेटा संरचनाओं को वापस कर देंगे जो डेटाबेस टेबल की स्कीमा का खुलासा करते हैं (उदाहरण के लिए, डेटाटेबल्स या डेटा व्यू)।

तो, तर्क की सिफारिश की प्रवाह इस प्रकार है:

ASPX पेज एक डेटास्रोत नियंत्रण एक बीएल वर्ग के लिए बाध्य करने के लिए उपयोग करता है। यह बीएल वर्ग उचित कार्यों जैसे GetData, UpdateData, DeleteData and InsertData (किसी भी आवश्यक अधिभार के साथ) प्रदान करता है और ये फ़ंक्शन दृढ़ता से टाइप की गई वस्तुओं या संग्रहों को वापस लौटाते हैं जो ObjectDataSource काम कर सकते हैं और प्रदर्शित कर सकते हैं। बीएल क्लास में प्रत्येक सार्वजनिक फ़ंक्शन डेटाबेस से डेटा/डेटा को चुनने/अपडेट/हटाने/डालने के लिए आंतरिक रूप से डेटालेयर में कॉल करता है।

ASP.NET में इस परत आधारित डिजाइन करने के लिए एक उत्कृष्ट परिचय Quickstarts

पी.एस में प्रदान की जाती है: @Andy सामान्य datalayers कि सभी स्थितियों के साथ काम का उल्लेख किया। उदाहरण के लिए this question देखें कि यह कैसा दिखता है।

+0

शायद विषय बंद करें, लेकिन क्या मुझे डीएएल में मेरे उदाहरण में कनेक्शन बंद करने की आवश्यकता है? –

+0

आप मेरे वर्तमान कोड को ऊपर कैसे रेट करेंगे? –

+1

@ जोन: आपको इसे स्पष्ट रूप से बंद करने की आवश्यकता नहीं है क्योंकि आप "निर्माण का उपयोग" का उपयोग कर रहे हैं, जो कनेक्शन को निपटाने का प्रयास करेगा। उस ने कहा, आपको शायद स्पष्टता के लिए इसे बंद करना चाहिए। – Cerebrus

0

यदि आप अंततः पोर्टेबल होने के लिए अपना कोड लिखते हैं, तो आप पाएंगे कि आपके आवेदन में 3 (या अधिक!) परतें होंगी।

उदाहरण के लिए - अपने डेटा एक्सेस लेयर को विशेष रूप से इस एप्लिकेशन के लिए काम करने के बजाय, इसे लिखें ताकि आपको इसे फिर से लिखना पड़े। सुनिश्चित करें कि आपके सभी कार्यों को चर पारित किया जा सकता है और आप वैश्विक चर (या जितना संभव हो उतना छोटा) पर भरोसा नहीं करते हैं। जब आपकी अगली परियोजना के लिए समय आता है - अपने डीएएल की प्रतिलिपि बनाएं और चिपकाएं और अचानक आप ऊपर जा रहे हैं और फिर से चल रहे हैं।

और यह वहां समाप्त नहीं होता है - आप अपने डीएएल के लिए एक उप-परत लिखना चाहेंगे जो MySQL और MSSQL (जैसे एक उदाहरण के रूप में) के बीच व्याख्या करता है। या आपके पास सामान्य कार्यों की एक लाइब्रेरी हो सकती है जो आप करते हैं, जैसे पाठ स्वच्छता या सीएसएस पीढ़ी या कुछ।

यदि आप अपना कोड लिखते हैं तो एक दिन, आप एक ऐप लिखने के लिए बैठते हैं - और इसमें ज्यादातर कोड को काटने और पेस्ट करना शामिल है - आप प्रोग्रामर निर्वाण पहुंचे हैं। :)

+0

मुझे यह नहीं पता कि यह कैसे काम करेगा, माफ करना, मैं अभी भी यह सब सीख रहा हूं। यदि एक कार्यक्रम चालान के बारे में है और दूसरा मीडिया प्लेयर है तो दोनों एक ही डीएएल का उपयोग दोनों के लिए कैसे करेंगे? क्या दोनों कार्यक्रम अलग-अलग वर्गों और वस्तुओं का उपयोग नहीं करेंगे? –

+0

@ जॉन- भले ही उनके पास विभिन्न ऑब्जेक्ट्स और क्लासेस हों, फिर भी प्रत्येक – TStamper

+0

@Andy के लिए अलग-अलग प्रोजेक्ट फाइलें हो सकती हैं: दोनों प्रतिमान विभिन्न परिदृश्यों के लिए उपयुक्त हैं। कभी-कभी प्रत्येक प्रोजेक्ट के लिए एक विशिष्ट डाटलियर होना पसंद किया जाता है। जबकि मैं अपनी अधिकांश ज़रूरतों के लिए जेनेरिक डाटालायर का उपयोग करता हूं, मैं विशिष्ट डाटलियर बनाने की आवश्यकता को समझता हूं और विश्वास नहीं करता कि उन्हें निराश किया जाना चाहिए। – Cerebrus

0

एप्लिकेशन को लेयर करने के पीछे पूरा विचार यह है कि प्रत्येक परत नीचे परतों के कार्यान्वयन विवरण पर निर्भर नहीं होती है। उदाहरण के लिए, आपके कोड में आपके प्रस्तुति परत के अंदर एक टी-एसक्यूएल कथन है। इसका मतलब है कि आपके डेटाबेस (नीचे परत) पर आपकी प्रस्तुति परत की प्रत्यक्ष निर्भरता है। यदि आप अपने डेटाबेस में बदलाव करते हैं, तो आपको अपनी प्रस्तुति परत में भी बदलाव करना होगा। आदर्श रूप में यह वही नहीं है जो आप चाहते हैं। प्रस्तुति परत केवल डेटा प्रस्तुत करने के बारे में चिंतित होना चाहिए, इसे पुनर्प्राप्त करने के तरीके के बारे में नहीं। मान लें कि आप अपने पूरे डेटाबेस को सीएसवी फाइलों में ले जाते हैं (मुझे पता है, पागल विचार), तो आपकी प्रस्तुति परत को इस बारे में अवगत नहीं होना चाहिए।

तो आदर्श रूप में, आपके पास एक व्यापार परत विधि है जो केवल उस डेटा को लौटाती है जिसे आप उपयोगकर्ता को दिखाना चाहते हैं। आपको SqlDataSource के बजाय ObjectDataSource पर एक नज़र डालना चाहिए। SqlDataSource छोटी प्रोटोटाइप परियोजनाओं के लिए अच्छा है, लेकिन आपको इसे और अधिक गंभीर परियोजनाओं के लिए उपयोग नहीं करना चाहिए।

व्यापार परत और डेटा परत के बीच आपको एक समान अलगाव होना चाहिए। डेटा लेयर कुछ स्टोरेज स्थान (डेटाबेस, सीएसवी फ़ाइल, वेब सेवा, ...) से इच्छित डेटा प्राप्त करने के लिए ज़िम्मेदार है। फिर, आदर्श रूप से, व्यापार परत डेटा परत के कार्यान्वयन विवरण पर निर्भर नहीं होना चाहिए। उदाहरण के लिए यदि आप SQL सर्वर से बात कर रहे हैं, तो आपको SqlDataReader उदाहरण को अपनी व्यावसायिक परत पर वापस नहीं करना चाहिए। ऐसा करके आप अपनी डेटा परत के कार्यान्वयन विवरण पर अपनी व्यावसायिक परत की निर्भरता बनाते हैं: वास्तविक डेटाबेस यह इसके डेटा को पुनर्प्राप्त कर रहा है।

प्रैक्टिस में आप देखते हैं कि व्यापार परत डेटा परत के कार्यान्वयन विवरण पर किसी अन्य तरीके से निर्भर करती है और आमतौर पर यह एक बुरी चीज नहीं है। आखिरी बार कब आपने डेटाबेस स्विच करने का फैसला किया था? लेकिन निर्भरताओं को खत्म करना और जितना संभव हो सके कार्यान्वयन विवरण को अलग करना हमेशा एक ऐसे अनुप्रयोग में परिणाम होता है जो बनाए रखना और समझना आसान है।

आप एक समान स्पष्टीकरण here पा सकते हैं।

+0

धन्यवाद, मुझे ऑब्जेक्टडेटा स्रोत के बारे में पता नहीं था। इससे बहुत मदद मिली है! –

3

एएसपी.NET अनुप्रयोगों में तर्क परतों का सबसे बड़ा स्पष्टीकरण दो स्रोतों से आता है। पहला माइक्रोसॉफ्ट की अपनी एएसपी.नेट वेबसाइट स्कॉट मिशेल द्वारा लिखी गई है, यह तर्क के अलगाव के लिए एक अच्छा परिचय प्रदान करती है। ट्यूटोरियल काफी शब्दशः हैं लेकिन मैंने उन्हें बहुत उपयोगी पाया। यूआरएल http://www.asp.net/learn/data-access/ है।

दूसरा संसाधन मुझे बहुत उपयोगी पाया गया और यह इमर स्पानजाजार द्वारा लिखा गया था और here उपलब्ध है। यह एक बहुत अधिक तकनीकी लेख है लेकिन आपके आवेदन में संरचना जोड़ने का एक शानदार तरीका प्रदान करता है।

मुझे उम्मीद है कि इससे मदद मिलती है।

इयान।

+0

इमर स्पापानजार्स का लिंक बहुत उपयोगी था! –

+1

मुझे खुशी है कि आपको यह पसंद है मुझे इसे सीखने के लिए एक महान मध्यवर्ती संसाधन मिला। –

+0

मैंने अभी इमर के लेख को देखा है। सिर्फ एक साधारण सवाल - क्या यह कुख्यात "एनीमिक डोमेन मॉडल" का परिचय नहीं है? मेरा मतलब है कि मुझे अपनी व्यावसायिक वस्तुओं से अपने व्यापारिक सामान को अलग क्यों करना चाहिए, वैसे भी? और अगर मैं ऐसा करता हूं, तो मैं व्यवसाय वस्तु "व्यापार वस्तुओं" को क्यों बुलाऊंगा ?? – atiyar

0

अपने प्रश्न के मुख्य जोर के लिए एक तरफ के रूप में, मैं आपको अपने एसक्यूएल डेटाबेस को कॉन्फ़िगर करने के लिए ASPNET_REGSQL को देखने की सलाह दूंगा। नेट की अंतर्निहित सदस्यता/प्रोफ़ाइल/भूमिका क्षमताओं को संभालने के लिए। यह उपयोगकर्ताओं को बनाने/अपडेट करने के लिए बहुत सारी परेशानी और परेशानी को दूर कर देगा, आदि। मैंने प्रोफ़ाइल का उपयोग बहुत भयानक नहीं किया है, लेकिन यह आपको अपने उपयोगकर्ता को अतिरिक्त विशेषताओं "पर" करने की अनुमति देता है, उदाहरण के लिए एक्सेस कोड।

यदि आप मौजूदा डीबी संरचना से निपट रहे हैं जो पहले से ही उपयोगकर्ता प्रमाणीकरण आदि करता है, तो आप एक कस्टम सदस्यता प्रदाता बना सकते हैं जो मौजूदा डीबी टेबल और संग्रहीत प्रक्रियाओं का लाभ उठाएगा।