아래와 같이 그리드를 임의로 구성해 주었습니다.

 

        protected System.Web.UI.WebControls.DataGrid DataGrid1;

    

        private void Page_Load(object sender, System.EventArgs e)

        {

            DataSet ds = new DataSet();

            string[] strs;

 

            ds.Tables.Add("NewDT");

 

            ds.Tables["NewDT"].Columns.Add("f1");

            ds.Tables["NewDT"].Columns.Add("f2");

            ds.Tables["NewDT"].Columns.Add("f3");

 

            strs = new string[] {"1", "1", ""};

            for(int i=0; i<10; i++)

                ds.Tables["NewDT"].Rows.Add(strs);

            DataGrid1.DataSource = ds;

            DataGrid1.DataBind();

 

        }

 

 

아래와 같이 그리드를 설정해 주었습니다.

 

            <asp:datagrid id="DataGrid1" runat="server" PagerStyle-Visible="true" CssClass="green" ShowHeader="false"

                AutoGenerateColumns="False" BorderWidth="0" CellSpacing="0" CellPadding="0" GridLines="Horizontal">

                <Columns>

                    <asp:TemplateColumn HeaderText="No" HeaderStyle-CssClass="body2_8" HeaderStyle-BackColor="#3cadd3" HeaderStyle-Height="34"

                        ItemStyle-Width="30" ItemStyle-HorizontalAlign="Center" ItemStyle-Height="24">

                        <ItemTemplate>

                            <asp:TextBox id="TextBox1" runat="server" Text='<%# DataBinder.Eval(Container, "DataItem.f1") %>' onchange="Compute(this, 1, 2)"></asp:TextBox>

                        </ItemTemplate>

                    </asp:TemplateColumn>

                    <asp:TemplateColumn HeaderText="구분" HeaderStyle-CssClass="body2_8" HeaderStyle-BackColor="#3cadd3" ItemStyle-Width="30">

                        <ItemTemplate>

                            <asp:TextBox id="Textbox2" runat="server" Text='<%# DataBinder.Eval(Container, "DataItem.f2") %>' onchange="Compute(this, -1, 1)"></asp:TextBox>

                        </ItemTemplate>

                    </asp:TemplateColumn>

                    <asp:TemplateColumn HeaderText="모델명" HeaderStyle-CssClass="body2_8" HeaderStyle-BackColor="#3cadd3"

                        ItemStyle-Width="100">

                        <ItemTemplate>

                            <asp:TextBox id="Textbox3" runat="server" Text='<%# DataBinder.Eval(Container, "DataItem.f3") %>'></asp:TextBox>

                        </ItemTemplate>

                    </asp:TemplateColumn>

                </Columns>

            </asp:datagrid>

 

 

아래와 같이 자바스크립트 함수를 구현했습니다.

 

        <script language="javascript">

        function Compute(TextBox, POS, result){

            var TextBoxs = document.getElementsByTagName('INPUT');

            

            for(i=0;i<TextBoxs.length;i++){

                if(TextBoxs[i] == TextBox)

                    TextBoxs[i+result].value = parseInt(TextBox.value) + parseInt(TextBoxs[i+POS].value)

            }

        }

        </script>

 

 

getElementsByTagName은 6.0이후에 지원되는 함수라는 말이 있습니다. 제가 6.0을 사용하고 있기 때문에 확인해 본바는 아니구요.

 

처음 답변에 있던 URL의 게시판에 보시면 6.0이전에서 사용되는 함수를 올려 놓은 것이 있을겁니다. 검색에서 name에 'miniaron'으로 검색하시면 나옵니다.

 

 

프로젝트 실제 코드를 함께 올려드리니 참고하십시요.

 

성공하시면 답변 주시고요.

 

성공을 기원합니다.

 

등대지기 황상범

 

 

에구구...사내 보안관련해서 화일이 업로드 되지 않는 관계로 URL을 적습니다.

http://www.lottokeno.co.kr/Proj_01.zip

 

 

 

데이터그리드편집속성에서 특정컬럼에 TemplateColumn을 추가한후 그안에 textBox를 추가했을경우 Page_Load 이벤트내의 코드를 해주지 않으면 컴파일후 DataGrid에 빈 DataTable이 바인딩된 상태가 되지 않는다.. 이유는 모름..연구중..


Posted by 뭉치냐옹
:
public void GetMyRecords() {
   // ...
   // create myDataSet and myDataAdapter
   // ...
   myDataAdapter.Fill(myDataSet,9,15,"Categories");
}


 

DataSetDataTable 이름을 사용하여 지정된 범위에서 데이터 소스의 행과 일치하도록 DataSet의 행을 추가하거나 새로 고칩니다.

public int Fill(
   DataSet dataSet,
   int startRecord,
   int maxRecords,
   string srcTable
);

매개 변수

dataSet
레코드와 스키마(필요한 경우)로 채울 DataSet입니다.
startRecord
0부터 시작되는 시작 레코드 번호입니다.
maxRecords
검색할 수 있는 최대 레코드 수입니다.
srcTable
테이블 매핑에 사용할 원본 테이블의 이름입니다.

반환 값

DataSet에서 성공적으로 추가했거나 새로 고친 행의 수입니다. 이것은 행을 반환하지 않는 문의 영향을 받는 행을 포함하지 않습니다.


Posted by 뭉치냐옹
:

계속 데브피아에서 도움만 받기에 그동안의 고마운 마음을 담아,

허접한 자료이지만 데브피아에서 얻은 자료와 개인적으로 알아낸 방법들을 모아서 MDB사용하는데 어려움을 느끼시는 분들을 위해 올립니다.

 

흑흨~ 이거 알아 내는데 너무도 많은 시간이 결렸습니당~

 

처음엔 데이터를 엑셀로 옮겨서 사용했었는데, 옮기는 시간이.. 장난이 아니더군요, DAO를 사용하면 엄청난 속도 향상을 느끼실 수 있을 겁니다.

다량의 데이터를 사용하실 때는 MDB로 옮겨서 엑셀로 보내는 것이 정신건강상 유리할듯 ㅎ~

 

먼저 DAO를 이용했기 때문에 DAO를 참조하고, 나중에 압축할 것이기 때문에 JDO도 참조하셔야 합니다.

그리고 임시파일을 제거할 때 IO를 사용하기 때문에, DAO가 소문자로 참조되었기 때문에 개인적으로 불편해서 넣은 코드인

 

using System.IO;

using DAO = dao;

 

를 넣어줘야 합니다.

 

 

아래 부터 코드입니다. 현재 작업중인 관계로 원본 코드 그대로 올리니, 이해바랍니당~ ㅋㅋ~

 

                string mdbName = "분석자료";

                

                string 원본mdb = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\" + mdbName + ".mdb";

                string 임시mdb = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\" + "tmpdb" + ".mdb";

 

                DAO.DBEngineClass db = new DAO.DBEngineClass();

                DAO.Workspace dbw = db.Workspaces[0];

                DAO.Database db1;

 

            

                //MDB 생성

                dbw.CreateDatabase(임시mdb, DAO.LanguageConstants.dbLangKorean, DAO.DatabaseTypeEnum.dbVersion40);

 

                //MDB 열기

                db1 = dbw.OpenDatabase

(임시mdb, DAO.DatabaseTypeEnum.dbVersion40, (object)false, DAO.LanguageConstants.dbLangKorean);

 

                //테이블 생성

                DAO.TableDef dt = db1.CreateTableDef("T인력분석",Type.Missing,Type.Missing,Type.Missing);

                DAO.Field df = dt.CreateField("ID_인력분석",DAO.DataTypeEnum.dbLong,4);

                df.Attributes = 17; //중요! 해당 필드를 일련번호로 만듬

 

                dt.Fields.Append(df);

 

                for(int i=0; objds자봉자료.T인력분석.Columns.Count -1 >= i; i++)

                {

                    if((objds자봉자료.T인력분석.Columns[i].ColumnName.ToString() != "") && (objds자봉자료.T인력분석.Columns[i].ColumnName != "ID_인력분석"))

                    {

                        string 필드이름 = objds자봉자료.T인력분석.Columns[i].ColumnName.ToString();

                        DAO.Field df1 = dt.CreateField(필드이름,DAO.DataTypeEnum.dbText,50);

                        df1.AllowZeroLength = true;

                        df1.Required = false;

                        dt.Fields.Append(df1);

                    }

                                                                                                                            

                }

 

                db1.TableDefs.Append(dt);

 

                //인덱스 생성

                DAO.Index di = dt.CreateIndex("ID");

                di.Fields = "ID_인력분석";

                di.Primary = true;

                

                db1.TableDefs["T인력분석"].Indexes.Append(di);

 

                dao.Recordset rs =

                db1.TableDefs["T인력분석"].OpenRecordset(dao.RecordsetTypeEnum.dbOpenDynaset,dao.RecordsetOptionEnum.dbDenyWrite);

 

 

                for(int ii = 0; objds자봉자료.T인력분석.Count-1 >= ii; ii++)

                {

                    rs.AddNew();

 

                    for(int i=0; objds자봉자료.T인력분석.Columns.Count -1 >= i; i++)

                    {

                        if(objds자봉자료.T인력분석.Columns[i].ColumnName != "ID_인력분석")

                        {

                            rs.Fields[i].Value = objds자봉자료.T인력분석[ii][i].ToString();

 

                        }

                                                                                                                            

                    }

 

                    rs.Update(1,false);  //이거 알아내느라 또 몇시간 보냄 위에서 오픈할때의 타입과 연관있음.

                }

 

                

                //사용했던것 모두 닫습니다. 안닫으면 압축할때  에러납니다.

                rs.Close();

                db1.Close();

                dbw.Close();

                

                rs = null;

                db1 = null;

                dbw = null;

                db = null;

 

 

 

                //MDB 압축하기 강좌에 있는 TIP 그대로 배꼈습니다.

                JRO.JetEngineClass jro = new JRO.JetEngineClass();

                jro.CompactDatabase("Provider=Microsoft.jet.OLEDB.4.0;Data Source=" + 임시mdb,"Provider=Microsoft.jet.OLEDB.4.0;Data Source=" + 원본mdb);

 

 

                //임시 파일이 남아있으면 나중에 다시 압축할 때 에러납니다. (지금까지 작업했던 임시mdb가 임시파일임)

                FileInfo ff = new FileInfo(임시mdb);

                ff.Delete();

 

 

                MessageBox.Show("완료되었습니다.");

 

이상입니다.

허접한 코드이지만 용기내서 올려봅니다.


Posted by 뭉치냐옹
:

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.IO;

namespace 폴더_자동복사
{
 /// <summary>
 /// Form1에 대한 요약 설명입니다.
 /// </summary>
 public class Form1 : System.Windows.Forms.Form
 {
  private System.Windows.Forms.TextBox txtCopy;
  private System.Windows.Forms.TextBox txtOriginate;
  private System.Windows.Forms.Label label1;
  private System.Windows.Forms.Label label2;
  private System.Windows.Forms.Label lblMsg;
  private System.Windows.Forms.Button btnSelect;
  private System.Windows.Forms.Label label3;
  private System.Windows.Forms.Button btnServerCmbCopy;
  private System.Windows.Forms.Button btnServerAllCopy;

  string sOriginateName = "";
  string sCopyName = "";
  private System.Windows.Forms.ComboBox cmbPath;
  private System.Windows.Forms.ProgressBar pBar1;
  /// <summary>
  /// 필수 디자이너 변수입니다.
  /// </summary>
  private System.ComponentModel.Container components = null;

  public Form1()
  {
   InitializeComponent();

   
  }

  /// <summary>
  /// 사용 중인 모든 리소스를 정리합니다.
  /// </summary>
  protected override void Dispose( bool disposing )
  {
   if( disposing )
   {
    if (components != null)
    {
     components.Dispose();
    }
   }
   base.Dispose( disposing );
  }

  #region Windows Form Designer generated code
  /// <summary>
  /// 디자이너 지원에 필요한 메서드입니다.
  /// 이 메서드의 내용을 코드 편집기로 수정하지 마십시오.
  /// </summary>
  private void InitializeComponent()
  {
   this.btnSelect = new System.Windows.Forms.Button();
   this.txtCopy = new System.Windows.Forms.TextBox();
   this.txtOriginate = new System.Windows.Forms.TextBox();
   this.label1 = new System.Windows.Forms.Label();
   this.label2 = new System.Windows.Forms.Label();
   this.lblMsg = new System.Windows.Forms.Label();
   this.cmbPath = new System.Windows.Forms.ComboBox();
   this.label3 = new System.Windows.Forms.Label();
   this.btnServerCmbCopy = new System.Windows.Forms.Button();
   this.btnServerAllCopy = new System.Windows.Forms.Button();
   this.pBar1 = new System.Windows.Forms.ProgressBar();
   this.SuspendLayout();
   //
   // btnSelect
   //
   this.btnSelect.Location = new System.Drawing.Point(480, 7);
   this.btnSelect.Name = "btnSelect";
   this.btnSelect.Size = new System.Drawing.Size(104, 55);
   this.btnSelect.TabIndex = 0;
   this.btnSelect.Text = "선택백업";
   this.btnSelect.Click += new System.EventHandler(this.btnSelect_Click);
   //
   // txtCopy
   //
   this.txtCopy.Location = new System.Drawing.Point(48, 40);
   this.txtCopy.Name = "txtCopy";
   this.txtCopy.Size = new System.Drawing.Size(420, 21);
   this.txtCopy.TabIndex = 2;
   this.txtCopy.Text = "";
   //
   // txtOriginate
   //
   this.txtOriginate.Location = new System.Drawing.Point(48, 8);
   this.txtOriginate.Name = "txtOriginate";
   this.txtOriginate.Size = new System.Drawing.Size(420, 21);
   this.txtOriginate.TabIndex = 1;
   this.txtOriginate.Text = "D:\\WebSource\\TestWebRoot\\DirectAngelSolution\\DirectAngel\\bin";
   //
   // label1
   //
   this.label1.Location = new System.Drawing.Point(8, 13);
   this.label1.Name = "label1";
   this.label1.Size = new System.Drawing.Size(32, 23);
   this.label1.TabIndex = 3;
   this.label1.Text = "원본";
   //
   // label2
   //
   this.label2.Location = new System.Drawing.Point(8, 45);
   this.label2.Name = "label2";
   this.label2.Size = new System.Drawing.Size(32, 23);
   this.label2.TabIndex = 4;
   this.label2.Text = "복사";
   //
   // lblMsg
   //
   this.lblMsg.Font = new System.Drawing.Font("굴림", 10F);
   this.lblMsg.Location = new System.Drawing.Point(16, 180);
   this.lblMsg.Name = "lblMsg";
   this.lblMsg.Size = new System.Drawing.Size(568, 80);
   this.lblMsg.TabIndex = 5;
   this.lblMsg.Text = "<처리결과>";
   //
   // cmbPath
   //
   this.cmbPath.Items.AddRange(new object[] {
               "D:\\WebSource\\TestWebRoot\\TyLifeSolution\\TyLifeWeb\\bin",
               "D:\\WebSource\\TestWebRoot\\DirectAngelSolution\\DirectAngel\\bin",
               "D:\\WebSource\\TestWebRoot\\DirectAngelSolution\\Miclub\\bin",
               "D:\\WebSource\\TestWebRoot\\DirectAngelSolution\\HanaFos\\bin",
               "D:\\WebSource\\WebRoot\\TyLifeSolution\\TyLifeWeb\\bin",
               "D:\\WebSource\\WebRoot\\DirectAngelSolution\\DirectAngel\\bin",
               "D:\\WebSource\\WebRoot\\DirectAngelSolution\\Miclub\\bin",
               "D:\\WebSource\\WebRoot\\DirectAngelSolution\\HanaFos\\bin"});
   this.cmbPath.Location = new System.Drawing.Point(48, 104);
   this.cmbPath.Name = "cmbPath";
   this.cmbPath.Size = new System.Drawing.Size(420, 20);
   this.cmbPath.TabIndex = 7;
   this.cmbPath.Text = "선택";
   //
   // label3
   //
   this.label3.Location = new System.Drawing.Point(8, 108);
   this.label3.Name = "label3";
   this.label3.Size = new System.Drawing.Size(40, 23);
   this.label3.TabIndex = 8;
   this.label3.Text = "실섭";
   //
   // btnServerCmbCopy
   //
   this.btnServerCmbCopy.Location = new System.Drawing.Point(480, 104);
   this.btnServerCmbCopy.Name = "btnServerCmbCopy";
   this.btnServerCmbCopy.Size = new System.Drawing.Size(104, 23);
   this.btnServerCmbCopy.TabIndex = 9;
   this.btnServerCmbCopy.Text = "콤보선택백업";
   this.btnServerCmbCopy.Click += new System.EventHandler(this.btnServerCmbCopy_Click);
   //
   // btnServerAllCopy
   //
   this.btnServerAllCopy.Location = new System.Drawing.Point(480, 136);
   this.btnServerAllCopy.Name = "btnServerAllCopy";
   this.btnServerAllCopy.Size = new System.Drawing.Size(104, 23);
   this.btnServerAllCopy.TabIndex = 10;
   this.btnServerAllCopy.Text = "전체백업";
   this.btnServerAllCopy.Click += new System.EventHandler(this.btnServerAllCopy_Click);
   //
   // pBar1
   //
   this.pBar1.Location = new System.Drawing.Point(48, 136);
   this.pBar1.Name = "pBar1";
   this.pBar1.Size = new System.Drawing.Size(420, 23);
   this.pBar1.TabIndex = 12;
   //
   // Form1
   //
   this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
   this.ClientSize = new System.Drawing.Size(592, 273);
   this.Controls.AddRange(new System.Windows.Forms.Control[] {
                    this.pBar1,
                    this.btnServerAllCopy,
                    this.btnServerCmbCopy,
                    this.label3,
                    this.cmbPath,
                    this.lblMsg,
                    this.label2,
                    this.label1,
                    this.txtCopy,
                    this.txtOriginate,
                    this.btnSelect});
   this.Name = "Form1";
   this.Text = "Form1";
   this.ResumeLayout(false);

  }
  #endregion

  /// <summary>
  /// 해당 응용 프로그램의 주 진입점입니다.
  /// </summary>
  [STAThread]
  static void Main()
  {
   Application.Run(new Form1());
  }

  private bool SetFileCopy(string sOriginateName, string sCopyName)
  {
   bool bFlag = true;

   if(Directory.Exists(sOriginateName))
   {
    int iFlag = 1;
    string sTempName = sCopyName;

    while(Directory.Exists(sCopyName))
    {
     sCopyName = sTempName + "_" + iFlag.ToString();;
     iFlag++;
                }

    Directory.CreateDirectory(sCopyName);

    try
    {
     string sFileName = "";
     string[] files = Directory.GetFiles(sOriginateName);
     for(int i=0; i<files.Length; i++)
     {
      sFileName = Path.GetFileName(files[i]);
      File.Copy(files[i], sCopyName + "\\" + sFileName, false);
     }

     lblMsg.Text = "<처리결과>\n\n디렉토리 복사 완료";
   

    }
    catch(Exception ex)
    {
     lblMsg.Text = "<처리결과>\n\n" + ex.Message;
     bFlag = false;
    }
   }
   else
   {
    //원본디렉토리미존재
    lblMsg.Text = "<처리결과>\n\n원본 디렉토리 미존재";
    bFlag = false;
   }

   return bFlag;
  }

  private void SetProgressBar(int iCnt)
  {
   
   pBar1.Visible = true;
   pBar1.Minimum = 1;
   pBar1.Maximum = iCnt;
   pBar1.Value = 1;
   pBar1.Step = 1;

  }

  private void btnSelect_Click(object sender, System.EventArgs e)
  {
   sOriginateName = txtOriginate.Text;
   sCopyName = "";
   if(txtCopy.Text.Trim() == "")
    sCopyName = sOriginateName + "\\" + DateTime.Now.ToString("yyMMdd_HHmm");
   else
    sCopyName = txtCopy.Text;

   SetProgressBar(2);

   for(int i=0; i<1; i++)
   {
    if(!SetFileCopy(sOriginateName, sCopyName))
     break;
    else
    {     
     pBar1.PerformStep();
    }
   }
  }

  private void btnServerCmbCopy_Click(object sender, System.EventArgs e)
  {
   if(cmbPath.Text != "선택")
   {
    sOriginateName = cmbPath.Text;
    sCopyName = sOriginateName + "\\" + DateTime.Now.ToString("yyMMdd_HHmm");

    SetProgressBar(2);

    for(int i=0; i<1; i++)
    {
     if(!SetFileCopy(sOriginateName, sCopyName))
      break;
     else
     {
      pBar1.PerformStep();
     }
    }
   }
   else
   {
    lblMsg.Text = "<처리결과>\n\n선택 하세요";
   }
  }

  private void btnServerAllCopy_Click(object sender, System.EventArgs e)
  {
   int iCnt = cmbPath.Items.Count;

   SetProgressBar(iCnt);

   for(int i=0; i<iCnt; i++)
   {
    Object selectedItem = cmbPath.Items[i];

    sOriginateName = selectedItem.ToString();
    sCopyName = sOriginateName + "\\" + DateTime.Now.ToString("yyMMdd_HHmm");

    if(!SetFileCopy(sOriginateName, sCopyName))
     break;
    else
    {
     pBar1.PerformStep();
    }
   }
  }

 }
}

 

 

 

 

 

/*

웹서버의 여러개의 bin 폴더를 백업할때 수작업으로 하던 작업을 자동화하기 위해 만들어본 프로그램 입니다.

새롭게 복사되는 폴더명은 "년월일_시분" 또는 "년월일_시분_*"(1씩증가) 형식으로 정해집니다.

*/


Posted by 뭉치냐옹
:

콤마찍기

string.Format("{0:#,0}", 값)
string.Format("{0,9:N0}", row["field"]) + "원"; 



콤마제거

string[] itemAmount = null;  //금액(Split처리용)
string itemAmount2 = null;   //금액(,제거한 값)

itemAmount = ItemChild.ChildNodes[4].InnerText.Split(new Char[] { ',' });

for (int j = 0; j < itemAmount.Length; j++)
{
 itemAmount2 += itemAmount[j];
}


Posted by 뭉치냐옹
:

foreach(Control ctl in this.Controls)
{
    if(ctl.GetType()== typeof(Label))
    {
        MessageBox.Show(ctl.Name);
    }
}

폼 위의 컨트롤 중 타입이 라벨인 것만 찾습니다...
혹은 인터페이스를 사용 하셔도 됩니다..

IEnumerator myEnurator = this.Controls.GetEnumerator();
while(myEnurator.MoveNext())
{
    if(myEnurator.Current.GetType() == typeof(Label))
    {
        MessageBox.Show(((Label)myEnurator.Current).Name);
    }
}

Posted by 뭉치냐옹
:

/// <summary>
  /// 반올림 함수
  /// </summary>
  /// <param name="obj">반올림하고자 하는 값</param>
  /// <param name="dgt">표시하고자 하는 소숫점 자리수</param>
  /// <returns></returns>
  public static string GetFormattedString( object obj, int dgt )
  {
   double cv = 0;
   string dumStr = string.Empty;
   int totLen = 2 + dgt;

   for( int i = 0; i < dgt; i ++ )
    dumStr += "0";

   if( obj == null )
    return "0." + dumStr;

   if( obj is string )
   {
    if(Convert.ToString(obj as string).Trim() == string.Empty )
    {
     return "0." + dumStr;
    }
    cv = double.Parse(Convert.ToString(obj as string).Trim());
   }
   else if( obj is double )
   {
    cv = (double)obj;
   }
   else if( obj is int )
   {
    cv = (int)obj;
   }
   else if ( obj is float )
   {
    cv = (float)obj;
   }

   // Gets a NumberFormatInfo associated with the en-US culture.
   System.Globalization.NumberFormatInfo nfi = new System.Globalization.CultureInfo( "en-US", false ).NumberFormat;
   // Displays the same value with four decimal digits.
   nfi.NumberDecimalDigits = dgt;

   return cv.ToString( "N", nfi );
  }


Posted by 뭉치냐옹
:

.aspx.cs

strEvtComID = "0x0000000000000034";

Biz.매서드(int.Parse( strEvtComID.Replace( "0x", "" ), NumberStyles.HexNumber ))  // int.Parse로 형변환

 

.Biz.cs

public int put_WB_Consult_Product(int _TY_EventCompany_ID)
  {
   SqlParameter[] p = new SqlParameter[0];

   try
   {
    p[0] = new SqlParameter( "@TY_WB_Customer_Consult_Id" , SqlDbType.BigInt);
    p[0].Value = _PK;

    return this.DbAccess.RunSPNonQuery( "SP_WB_Event_Consult_INSERT", Site.GetReplace(p) );
   }
   catch ( Exception ex )
   {
    this.TraceWrite( System.Diagnostics.TraceLevel.Error, ex.Message ); // 에러를 로그파일에 입력

    return 0;
   }
  }

 

 

SP

CREATE  PROCEDURE SP_WB_Event_Consult_INSERT
    @TY_WB_Customer_Consult_Id BINARY(8)

 

 

Table

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[TY_WB_Customer_Consult]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[TY_WB_Customer_Consult]
GO

CREATE TABLE [dbo].[TY_WB_Customer_Consult] (
 [Contact_Id] [binary] (8) NULL ,
 [C_idx] [int] NULL ,
 [Product_Id] [binary] (8) NULL ,
 [Product_Name] [varchar] (100) COLLATE Korean_Wansung_CI_AS NULL ,
 ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO


Posted by 뭉치냐옹
:

변수명.PadLeft(2, '0');


Posted by 뭉치냐옹
:
using System;

 using System.Globalization;

 

public class MainClass {

    public static void Main(string[] args)  {

        DateTime dt = DateTime.Now;

        String[] format = {

            "d", "D",

            "f", "F",

            "g", "G",

            "m",

            "r",

            "s",

            "t", "T",

            "u", "U",

            "y",

            "dddd, MMMM dd yyyy",

            "ddd, MMM d \"'\"yy",

            "dddd, MMMM dd",

            "M/yy",

            "dd-MM-yy",

        };

        String date;

        for (int i = 0; i < format.Length; i++) {

            date = dt.ToString(format[i], DateTimeFormatInfo.InvariantInfo);

            Console.WriteLine(String.Concat(format[i], " :" , date));

        }

 

   /** Output.

    *

    * d :08/17/2000

    * D :Thursday, August 17, 2000

    * f :Thursday, August 17, 2000 16:32

    * F :Thursday, August 17, 2000 16:32:32

    * g :08/17/2000 16:32

    * G :08/17/2000 16:32:32

    * m :August 17

    * r :Thu, 17 Aug 2000 23:32:32 GMT

    * s :2000-08-17T16:32:32

    * t :16:32

    * T :16:32:32

    * u :2000-08-17 23:32:32Z

    * U :Thursday, August 17, 2000 23:32:32

    * y :August, 2000

    * dddd, MMMM dd yyyy :Thursday, August 17 2000

    * ddd, MMM d "'"yy :Thu, Aug 17 '00

    * dddd, MMMM dd :Thursday, August 17

    * M/yy :8/00

    * dd-MM-yy :17-08-00

    */

    }

}


Posted by 뭉치냐옹
:

l         .NET 날짜와 시간 표시 부분만을 정리 것입니다.

 

Item

Description

Format

Year

4 digit Year with century (1998 or 2003)

yyyy

2 digit Year without century (98 or 03)

yy

1,3 digit Year (3 for 2003)

y

Era (BC/AD)

gg

Month

Month as a decimal (02)

MM

Month without leading zero (2)

M

Abbreviated month name (Feb)

MMM

Full month name (February)

MMMM

Week

Abbreviated day name (Fri)

ddd

Weekday Name (Friday)

dddd

Day

Day of the month (03)

dd

Day without leading zero (3)

d

Time

Hour in 24 hour format (24)

H,HH

Hour in 12 hour format (03)

h,hh

Minute of hour as an integer (01)

m,mm

Second in minute (55)

ss

Second in minute with no leading zero (5)

s

 

l         아래는 Format 문자열을 이용한 예제 코드입니다.

 

using System;

 

class Program

{

  static void Main(string[] args)

  {

      Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd"));

      Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd hh:ss"));

      Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd hh:ss.fff"));

      Console.WriteLine(DateTime.Now.ToString("(tt) yyyy-MM-dd hh:ss.fff"));

      Console.WriteLine(DateTime.Now.ToString("(tt) yyyy-MM-dd hh:ss.fffzz"));

}

}

 

l         아래는 예제 코드를 실행 결과입니다.

 2006-03-21

2006-03-21 11:35

2006-03-21 11:35.206

(오전) 2006-03-21 11:35.206

(오전) 2006-03-21 11:35.206+09

Posted by 뭉치냐옹
:

IFRAME 처럼 기본적으로 HTML 콘트롤에 포함되지 않는 콘트롤을 runat=server 처리를 해도...

어트리뷰트를 자유롭게 콘트롤 하기 어렵습니다.

이때... Attributes.Add() 메서드로 처리하면 간단합니다.

 

아래의 비하인드 코드의 예를 듭니다.

string oSbQuery = string.Empty;

oSbQuery.Append("../Formselect/LoadDocument.aspx").Append(this.Request.Url.Query);

this.ifrForm.Attributes.Add("src", oSbQuery.ToString());


Posted by 뭉치냐옹
:
<%@ Page Language="C#" AutoEventWireup="True" %>
<%@ Import Namespace="System.Data" %>
 
<html>
   <script runat="server">
 
      ICollection CreateDataSource() 
      {
      
         // Create sample data for the DataList control.
         DataTable dt = new DataTable();
         DataRow dr;
 
         // Define the columns of the table.
         dt.Columns.Add(new DataColumn("IntegerValue", typeof(Int32)));
         dt.Columns.Add(new DataColumn("StringValue", typeof(String)));
         dt.Columns.Add(new DataColumn("CurrencyValue", typeof(double)));
         dt.Columns.Add(new DataColumn("ImageValue", typeof(String)));
 
         // Populate the table with sample values.
         for (int i = 0; i < 9; i++) 
         {
            dr = dt.NewRow();
 
            dr[0] = i;
            dr[1] = "Description for item " + i.ToString();
            dr[2] = 1.23 * (i + 1);
            dr[3] = "Image" + i.ToString() + ".jpg";
 
            dt.Rows.Add(dr);
         }
 
         DataView dv = new DataView(dt);
         return dv;
      }
 
 
      void Page_Load(Object sender, EventArgs e) 
      {

         // Load sample data only once, when the page is first loaded.
         if (!IsPostBack) 
         {
            ItemsList.DataSource = CreateDataSource();
            ItemsList.DataBind();
         }

      }
 
   </script>
 
<body>
 
   <form runat=server>

      <h3>DataList Example</h3>
 
      <asp:DataList id="ItemsList"
           BorderColor="black"
           CellPadding="5"
           CellSpacing="5"
           RepeatDirection="Vertical"
           RepeatLayout="Table"
           RepeatColumns="3"
           ShowBorder="True"
           runat="server">

         <HeaderStyle BackColor="#aaaadd">
         </HeaderStyle>

         <AlternatingItemStyle BackColor="Gainsboro">
         </AlternatingItemStyle>

         <HeaderTemplate>

            List of items

         </HeaderTemplate>
               
         <ItemTemplate>

            Description: <br>
            <%# DataBinder.Eval(Container.DataItem, "StringValue") %>

            <br>

            Price: <%# DataBinder.Eval(Container.DataItem, "CurrencyValue", "{0:c}") %>

            <br>

            <asp:Image id="ProductImage"
                 ImageUrl='<%# DataBinder.Eval(Container.DataItem, "ImageValue") %>'
                 runat="server"/>

         </ItemTemplate>
 
      </asp:DataList>
 
   </form>
 
</body>
</html>

----------------------------------------------------------------------------------------------------------------------------------              

 더간단 방법 ㅋ

 

  DataTable dt = new DataTable();
                DataRow dr;
                dt.Columns.Add("title");               
                dr = dt.NewRow();
                dr["title"] = "데이터가 없습니다.";
                dt.Rows.Add(dr);

                this.DataListTest.DataSource = dt;
                DataListTest.DataBind();

Posted by 뭉치냐옹
:

Transaction Processing (.NET)

 

목 차

1. Processing Transactions (개요)

2. Transaction Processing Fundamentals

     2.1 ACID Properties

     2.2 Transaction Boundaries

     2.3 Distributed Transaction

3. Transaction Models

     3.1 Manual Transaction

transaction processing.doc

           3.1.1 Manual Transactions and ADO.NET

           3.1.2 Manual Transactions and MSMQ

     3.2 Automatic Transaction

           3.2.1 Automatic Transaction Processing

           3.2.2 Automatic Transactions and ASP.NET

           3.2.3 Automatic Transactions and .NET Framework Classes

           3.2.4 Automatic Transactions and Web Services

           3.2.5 Voting in an Automatic Transaction


 

1. Processing Transaction (개요)

 

  트랜잭션은 트랜잭션 단위내의 모든 operation이 성공적으로 수행되지 않으면 data-oriented resource가 결코 업데이트 되지 않는 것을 보장한다. 관련된 operation을 완전성공 또는 완전실패의 unit에 조합함으로써 에러복구를 간단히 하고 어플리케이션의 신뢰성을 향상시킨다.

 

Microsoft .NET Framework하에서의 트랜잭션 처리에 관한 사항과 일반적인 트랜잭션 처리에 대한 사항을 알아보자.

 

 

2. Transaction Processing Fundamentals

   (기본적인 트랜잭션 처리의 용어와 개념소개)

 

         - 트랜잭션은 성공이나 실패의 단위로서 관련된 임무의 집합

- 트랜잭션은 commit 이나 abort 중에 하나이다.

- 트랜잭션은 여러 개의 수행을 같이 결합한다.

- 트랜잭션은 다양한 데이터 자원에 걸쳐 사용할 수 있다.

 

2-1. ACID properties

 

   ACID Atomicity, Consistency, Isolation, Durability를 상징한다. 이러한 특성들은 transaction“all or none”을 보장하기 위해 디자인되어 있고 많은 변수가 포함될 경우 복잡성을 줄여준다.

 

-         Atomicity : transaction은 작업의 한 단위이며, 단지 한번 실행되거나 또는 전혀 일어나지 않음을 나타낸다. (a unit of work)

-         Consistency : 데이터는 transaction 처리 동안 형태나 단위가 변하지 않는다. (a unit of integrity)

-         Isolation : transaction은 자신에 포함된 데이터를 처리하는 유일한 시스템처럼 작동한다. (a unit of isolation)

-         Durability : fault tolerance 기능을 한다. 데이터가 commit 된 직후 시스템에 에러가 발생하더라도 데이터의 안전을 보장한다. (a unit of recovery)

 

 

 

2-2. Transaction Boundaries

  

   transaction boundary는 트랜잭션의 범위를 한정한다. transaction boundary안의 object는 공통의 트랜잭션 식별자를 공유한다.

   트랜잭션이 실행됨에 따라, 다양한 트랜잭션 인식 자원들이 트랜잭션내에 참여할 수 있다. 예를 들면 트랜잭션 영역내에서 어플리케이션이 데이터베이스에 연결되면, 트랜잭션은 그 자원으로 흘러간다. 그리고 transaction boundary는 데이터베이스 서버를 포함하는 것으로 확장된다. 또한 process computer에 걸쳐서 트랜잭션을 디자인 할 수 있다. 따라서 transaction boundary process computer 사이에서 일관성을 관리하는 추상관념이라 할 수 있다.

   transaction boundary를 제어하는 것은 어플리케이션에서 선택한 transaction model (manual 또는 automatic) 에 따라 결정된다.

 

   Manual transaction에서는 트랜잭션을 시작하고 끝내는 명백한 지시어와 함께 트랜잭션 영역을 제어한다. 하나의 트랜잭션 영역 안에 또 다른 트랜잭션을 시작할 수 있다. 이것을 nested transaction이라 한다. 상위 트랜잭션은 하위 트랜잭션이 모두 commit될 때까지 commit 되지 않는다.

 

   Automatic transaction은 각 컴포넌트에서 선언된 attribute에서 따라서 트랜잭션 영역을 관리한다. 트랜잭션은 트랜잭션에 관계한다고 지시된 object로 흘러가고 트랜잭션 밖에서 실행된다고 지시된 object는 통과한다. 또한 Nested transaction을 사용할 수 없다.

 

 

2-3. Distributed Transactions

 

         분산 transaction processing(TP) 시스템이란 분산 환경에서 트랜잭션이  이기종간의 트랜잭션 인식 자원을 확장,연결하는 것을 도와준다. 분산 TP 시스템의 지원으로 어플리케이션이 다음과 같이 다양한 활동상태로 트랜잭션 unit을 구성할 수 있다. - MSMQ에서 메시지를 가져오고, Microsoft SQL Server database에 메시지를 저장하고 Oracle Server database에서 메시지가 참고하고 있는 것을 삭제할 수 있다.

         분산 TP 시스템은 몇 개의 상호 작용하는 entity로 구성되어 있다. 다음의 entity는 논리적이며, 같은 컴퓨터나 다른 컴퓨터에 존재할 수 있다.

 

- Transaction Processing (TP) Monitors

   : 트랜잭션 인식 어플리케이션과 자원의 집합 사이에 있는 소프트웨어이다. OS 활동을 극대화 하고, 네트워크 커뮤니케이션을 간소화 하고, 잠재적으로 다양한 데이터 자원에 접근하는 다양한 어플리케이션에 접근하는 많은 클라이언트와 접속하게 한다.

  Microsoft Windows 2000에서 TP monitor DTC이다.

 

- Transaction Managers

   : 분산 트랜잭션에서 참여하는 자원은 각각 local transaction manager (TM)을 가지고 있다. 이것은 입력과 출력 트랜잭션을 추적한다. TM은 모든 트랜잭션 처리 함수를 조정하고 관리하지만 데이터를 직접관리 하지 않는다.

 

- Resource Managers

   : resource manager는 시스템 서비스이다. 지속적이고 영속적으로 데이터와 message queue를 관리하고 트랜잭션 파일 시스템을 관리한다. Resource manager는 데이터를 저장하고 재난 복구를 수행한다.

 

- Resource Dispensers

   : resource dispenser는 공유되어 있는 비영속 상태를 관리한다. 예를 들어 ODBC resource dispenser는 더 이상 필요하지 않는 커넥션을 재사용하는 데이터베이스 커넥션 pool을 관리한다.

 

 

 

 

 

3. Transaction Models

 

         automatic transaction에 관련된 .NET Framework object에서,  .NET Framework class Windows 2000 Component Service에 등록해야 한다. 그러나 모든 transaction이 다 automatic인 것은 아니다.

 

 

3.1 Manual Transactions

 

         ADO, OLE DB, ODBC, MSMQ에서 manual transaction 프로세싱을 가능하다.  명확하게 트랜잭션을 시작하고, 각 커넥션과 자원의 제어하고, 트랜잭션의 결과(commit 또는 abort)를 결정하고, 트랜잭션을 끝낸다. 이 모델은 트랜잭션에 대한 기준 control을 제공하지만 automatic control model에 포함된 간편한 구조생성이 없다. 예를 들면, 자동 enlistment가 없고, 데이터 저장에서의 coordination이 없다. 또한 트랜잭션이 object에서 object로 흘러가지 않는다.

 

분산 트랜잭션을 수동으로 제어하기 위해서는  recovery, concurrency, security, integrity 를 관리해야 한다. , 트랜잭션 처리와 관련된 ACID 속성을 유지하기 위해 모든 프로그래밍 기술이 지원되어야 한다.

 

 

3.1.1 Manual Transactions and ADO.NET

 

SQL client OLE DB .NET provider common language runtime에서 manual transaction을 지원한다.

두개의 provider database connection을 생성하고 트랜잭션을 시작하고 commit하거나 roll back 하는 관리된 object를 포함한다.

ADO.NET 트랜잭션은 전적으로 데이터베이스 안에서 처리되며, Microsoft Distributed Transaction Coordinator(DTC)나 다른 트랜잭션 메커니즘을 지원하지 않는다.

 

  )  transaction 수행

트랜잭션은 논리적인 작업 단위로 묶이는 데이터베이스 동작의 그룹이다. 그리고 시스템에서 일어날 지 모르는 에러에도 불구하고 각 데이터베이스의 consistency integrity를 유지하고 제어하는 데 사용된다.

 

예를 들어서 자금이 하나의 계좌에서 다른 계좌로 이체된다고 할 경우, 한 계좌에는 금액이 빠져나가고, 다른 계좌에 같은 금액만큼 동시에 들어온다. 컴퓨터가 정전이 되거나, 네트워크가 불통되는 등 작동하지 않을 경우 때문에, 하나의 테이블에서 로우가 업데이트 되지만 관계된 테이블에 안 될 경우가 발생한 가능성이 있다. 만약 데이터베이스가 트랜잭션을 지원한다면, 이러한 사태에 대한 결과로 발생하는 데이터베이스의 불일치를 방지하기 위하여 데이터베이스 작업을 트랜잭션으로 그룹지어야 한다.

 

트랜잭션에 대한 3가지 기본 명령어가 있다. BEGIN, COMMIT, ROLLBACK.

BEGIN 명령어는 트랜잭션의 시작을 알린다. BEGIN 명령어 다음의 모든 procedure는 트랜잭션의 부분으로 간주되고 COMMIT 명령어에 의해 종결되거나, ROLLBACK 명령어에 의해 취소된다.

 

다음의 예를 Transaction-SQL을 사용한 트랜잭션 로직을 보여준다.

  BEGIN TRAN

         INSERT INTO account (account, amount, debitcredit) values (100, 100, ‘d’)

         INSERT INTO account (account, amount, debitcredit) values (300, 100, ‘d’)

  IF (@@ERROR > 0)

  ROLLBACK

  ELSE

  COMMIT

 

 

 

 

 

ADO.NET에서 ConnectionTransaction객체를 이용하여 트랜잭션을 제어한다.

트랜잭션 실행방법

1. 트랜잭션의 시작을 알리기 위해 Connection 객체의 BeginTransaction 메쏘드를 호출한다.

2. 요구되는 SQL 문장을 실행한다.

3. 트랜잭션을 완료하기 위해 Transaction 객체의 Commit 메쏘드를 호출하거나,

   트랜잭션을 취소하기 위해 Rollback 메쏘드를 호출한다.

 

SqlConnection myConnection = new SqlConnection("Data Source=localhost;Initial Catalog=Northwind;Integrated Security=SSPI;");

myConnection.Open();

 

// Start a local transaction.

SqlTransaction myTrans = myConnection.BeginTransaction();

 

// Assign a transaction object for a pending local transaction.

SqlCommand myCommand = new SqlCommand();

myCommand.Transaction = myTrans;

 

try

{

  myCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (100, 'Description')";

  myCommand.ExecuteNonQuery();

  myCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (101, 'Description')";

  myCommand.ExecuteNonQuery();

  myTrans.Commit();

  Console.WriteLine("Both records are written to database.");

}

catch(Exception e)

{

  myTrans.Rollback();

  Console.WriteLine(e.ToString());

  Console.WriteLine("Neither record was written to database.");

}

finally

{

  myConnection.Close();

}

 

주의 : DataSet 객체는 AcceptChanges RejectChanges 메쏘드를 사용하는 Commit 모델을 가진다. 그러나 이 모델은 데이터베이스에 영향을 미치지 않고 단지 DataSet의 데이터가 있는 캐시에 영향을 미친다.

3.1.2 Manual Transactions and MSMQ

    

관리 언어로 작성된 component MSMQ에서 메시지를 보내거나 받을 수 있다.

 

   MSMQ는 어플리케이션에서 message queuing을 실행하는 기술이다. MSMQ로 메시지 queue들을 생성하거나 삭제할 수 있고, 메시지를 보내거나 받을 수 있고, 관리할 수 있다. 트랜잭션은 MSMQ의 비동기 능력을 요구하는 enterprise 시스템에서 중요한 부분이다.

 

   공통언어런타임은 MessageQueueTransaction Class를 통해서 manual transaction을 지원한다. MSMQ transaction은 전적으로 MSMQ 엔진 내에서 다루어진다.

 

 

3.2 Automatic Transactions

 

Microsoft Transaction Server(MTS), COM+ 1.0, 그리고 common language runtime은 동일한 automatic distributed transaction model을 지원한다. ASP.NET 페이지, Web Service method 또는 .NET Framework class transaction에 관계한다고 표시되면, 트랜잭션의 영역내에서 자동적으로 실행된다. 페이지, 웹서비스 method, 또는 class내의 트랜잭션 attribute 값을 셋팅하면 객체의 트랜잭션 행위를 제어할 수 있다. Attribute 값은 생성된 객체의 트랜잭션 행위를 결정한다. 따라서 선언된 attribute 값에 따라서 객체는 현재의 또는 다가올 트랜잭션에 관계하거나, 새로운 트랜잭션의 루트가 되거나, 트랜잭션에 전혀 관계하지 않을 수 있다. 트랜잭션 attribute 선언 구문은 .NET Framework class, ASP.NET page, 그리고 웹 서비스 method에서 조금씩 차이가 있다.

 

선언된 트랜잭션 attribute는 트랜잭션에 객체를 관련하는 방법을 설정하고, 프로그램적으로 구성된다. 비록 이 선언된 수준이 트랜잭션의 logic을 표현하지만, 이것은 물리적인 트랜잭션으로부터 제거된 하나의 스텝이다. 물리적인 트랜잭션은 트랜잭션 객체가 데이터베이스나 message queue와 같은 데이터 자원에 접근할 때 일어난다. 객체와 관련된 트랜잭션은 자동으로 적절한 자원관리자로 흘러간다. OLE DB, ODBC, ADO와 같은 관련된 driver는 객체의 문맥에서 트랜잭션을 찾고 DTC를 통해서 트랜잭션에 요청한다.

 

3.2.1 Automatic Transaction Processing

 

     Automatic Transaction Processing은 런타임시 트랜잭션에 관계시키기 위해 디자인 타임에서 클래스를 구성할 수 있게 하는 COM+에 의해 제공되는 서비스이다. 이 서비스를 사용하기 위해서 클래스는 System.EnterpriseServices.ServicedComponent class로부터 직, 간접적으로 상속되어져 있어야 한다.

 

3.2.2 Automatic Transaction and ASP.NET

 

ASP.NET Microsoft Windows 2000이 작동하는 시스템에서 automatic transaction을 지원한다. ASP.NET page에 트랜잭션 지시어를 삽입하여서 그 page가 기존의 트랜잭션에 관계하거나, 새로운 트랜잭션을 시작하거나, 또는 트랜잭션의 참여에 배제하는 것을 지시할 수 있다.

다음의 table ASP.NET에서 사용할수 있는 트랜잭션 지시어를 나타낸다.

 

지시어

    

Disabled

ASP.NET은 트랜잭션 문맥을 무시한다. 트랜잭션 상태의 default이다.

NotSupported

페이지가 트랜잭션 영역내에서 동작하지 않는 것을 나타낸다.

Supported

페이지가 기존의 트랜잭션 문맥내에서 동작하는 것을 나타낸다.

트랜잭션이 존재하지 않으면, 페이지는 트랜잭션 없이 동작한다.

Required

페이지가 기존의 트랜잭션 문맥내에서 동작하는 것을 나타낸다.

트랜잭션이 존재하지 않으면, 페이지는 한번 시작한다.

RequiresNew

페이지에 트랜잭션을 필요하고 각  요청에 새로운 트랜잭션을 시작한다.

 

코드내에 지시어를 넣어서 페이지가 지원하는 트랜잭션 레벨을 지시할 수 있다. 예를 들어, 다음의 지시어를 삽입하여 페이지 활동이 항상 트랜잭션 영역내에서 실행하는 것을 보증할 수 있다.

<%@ Page Transaction=”Required” %>

만약 트랜잭션 지시어를 생략하면 트랜잭션은 페이지 내에서 실행되지 않는다.

 

 

3.3.3 Automatic Transactions and .NET Framework Class

 

.NET Framework class의 개체는 automatic transaction에 관계할 수 있다. 예를 들어, 객체가 돈을 데이터베이스의 계좌로 보내기 위해 ADO.NET을 사용한다면 데이터베이스의  resource manager는 객체가 트랜젝션을 수행할 지를 결정한다. 그렇게 하여 그것은 자동적으로 데이터베이스에 기입된다.

 

Automatic transaction에 클래스를 관계시키기 위해 다음의 과정을 따른다.

1.      클래스에 TransactionAttribute 를 적용한다.

2.      ServicedComponent 클래스를 상속받는다.

3.      Sign the assembly with a strong name.

To sign the assembly using attributes create a key pair using the Sn.exe utility

Sn –k TestApp.snk

        

Add the AssemblyKeyFileAttribute or AssemblyKeyNameAttribute assembly attribute specifying the name of the file containing the key pair to sign the assembly with a strong name.

 

         [assembly: AssemblyKeyFileAttribute("TestApp.snk")]

 

4.      클래스를 포함하고 있는 assembly COM+ catalog로 등록한다.

만약 클래스의 인스턴스를 호출하는 클라이언트가 common language runtime으로 관리되면 등록이 수행이다. 그러나 비관리 호출이 일어나면 수동으로 등록하기 위해서 .NET Services Installation Tool(Regsvcs.exe)를 사용하여라.

 

다음의 예제는 ServicedComponent 클래스를 상속받는 클래스에 TransactionAttribute를 적용하는 방법을 보여준다.

[Transaction(TransactionOption.Required)]

public class Bar() : ServicedComponent

{

    // ……

}

transaction attribute를 적용할 때, Transaction, transaction, TransactionAttribute,  transactionattribute 를 다 사용할 수 있다.

 

다음의 테이블은 각각의 생성자 변화의 리스트와 설명을 나타낸다.

 

Attribute value

                   

Disabled

[Transaction(TransactionOption.Disabled)]

NotSupported

[Transaction(TransactionOption.NotSupported)]

Supported

[Transaction(TransactionOption.Supported)]

Required (default)

[Transaction(TransactionOption.Required)]

RequiredNew

[Transaction(TransactionOption.RequiredNew)]

 

 

 

 

 

 

 

Sample Class

   다음의 코드 예제는 automatic transaction의 몇 가지 요소를 보여준다. 이 예제에서 transaction 클래스와 클래스를 호출하는 클라이언트는 runtime에서 관리된다.

// -----------------------------------------------------------------
// TestApp.cs
// Generate a Strong name: 
//    sn -k TestApp.snk
// Compile the code:
//    csc /target:exe /r:System.EnterpriseServices.dll TestApp.cs
// Run TestApp:
//    start TestApp.exe
// -----------------------------------------------------------------
using System;
using System.Runtime.CompilerServices;
using System.EnterpriseServices;
using System.Reflection;
 
//Registration details.
//COM+ application name as it appears in the COM+ catalog.
[assembly: ApplicationName("TestApp")]
//Strong name for assembly.
[assembly: AssemblyKeyFileAttribute("TestApp.snk")]
 
[Transaction(TransactionOption.Required)]
public class Account : ServicedComponent
{
  //Provides SetComplete behavior in the absence of exceptions.
  [AutoComplete]
  public void Debit(int amount)
  {
     // Do some database work. Any exception thrown here aborts the 
     // transaction; otherwise, transaction commits.
  }
}
 
public class client
{
  public static int Main() 
  {
    Account accountX = new Account();
    accountX.Debit(100);
    return 0;
  }
}

 

3.3.4 Automatic Transaction and Web Services

 

   ASP.NET Web Forms 와 비슷하고 영속적인 추상관념을 프로그래밍에 사용하는, Web Service를 만들고 보여주는 미리 만들어진 지원을 사용한다. 결과적으로 확장성이 풍부한 모델이고, HTTP, XML, SOAP, WSDL 공개 인터넷 표준등을 포함한다. 이처럼 공개 표준을 지원하기 때문에, Web Service는 어떤 클라이언트나  인터넷이 가능한 장치로 접근하고 이용될 수 있다.

  

   Web Service automatic transaction의 영역내에서 코드가 실행될 수 있는 옵션을 제공한다.

   WebMethod attribute TransactionOption property를 사용하여 automatic transaction을 선언할 수 있다.  TransactionOption property TransactionOption.RequiresNew 라고 설정하면 웹 서비스 클라이언트가 웹 서비스 메쏘드를 호출할 때 마다 새로운 트랜잭션을 시작한다.

 

아래의 예제는 DeleteAuthor라는 한 웹 서비스 메쏘드를 실행하는 서비스를 보여준다.

<%@ WebService Language="C#" Class="Orders" %>

<%@ assembly name="System.EnterpriseServices" %>

 

using System;

using System.Data;

using System.Data.SqlClient;

using System.Web.Services;

using System.Web.Util;

using System.EnterpriseServices;

 

public class Orders : WebService

  {

     [ WebMethod(TransactionOption=TransactionOption.RequiresNew)]

     public int DeleteAuthor(string lastName) 

     {

       String deleteCmd = "DELETE FROM authors2 where au_lname='" +             lastName + "'" ;

   

         SqlConnection sqlConn = new SqlConnection("user

         id=sa;database=pubs;server=myserver");

         SqlCommand myCommand = new SqlCommand(deleteCmd,sqlConn);

 

   // If a Web Service method is participating in a transaction and an

   // exception occurs, ASP.NET automatically aborts the transaction.

   // Likewise, if no exception occurs, then the transaction is

   // automatically  committed.

 

         myCommand.Connection.Open();  

      return myCommand.ExecuteNonQuery();

     }

}

 

3.3.5 Voting in an Automatic Transaction

 

   .NET Framework class ASP.NET 페이지는 현재 트랜잭션을 commit하거나 abort 하는 것을 제안한다. 코드상에 명백하게 정해주지 않으면 default commit 이 된다.

   Default로 사용하는 commit은 각각의 트랜잭션이 자원을 release하는 시간을 길게 하기 때문에 어플리케이션의 성능을 저하한다.

 

AutoComplete 사용방법

 

  System.EnterpriseServices.AutoCompleteAttribute 는 메쏘드가 정상적으로 리턴되다면 트랜잭션을 완결하는 편으로 객체를 트랜잭션에 관계시킨다. 만약 메쏘드가 예외를 발생시키면, 트랜잭션은 실패한다.

ServicedComponent 클래스를 상속받는 클래스에만 이 attribute를 적용시킬 수 있다.

클래스 메쏘드 앞에 이 attribute를 작성한다. 만약 인터페이스 메쏘드에 attribute를 더할 경우 CLR은 이것을 무시한다.

[Transaction(TransactionOption.Supported)]
public class Account : ServicedComponent {
    [AutoComplete]
    public void Debit(int amount) {
        // Do some database work. Any exception thrown here aborts the transaction; 
        // otherwise, transaction commits.
    }
}

 

SetAbort SetComplete 사용방법

 

System.EnterpriseServices.ContextUtil 클래스를 사용하여 명백하게 트랜잭션을 commit 하거나 abort 할 수 있는 SetComplete SetAbort 메쏘드를 이용할 수 있다.

//Try to do something crucial to the transaction in progress.
if( !DoSomeWork() )
{
  //Something goes wrong.
  ContextUtil.SetAbort();
}
else
{
  //All goes well.
  ContextUtil.SetComplete();
     }


Posted by 뭉치냐옹
:

ASP.NET의 정규식

충돌 과정

Steven A. Smith

2004년 3월

적용 대상:
   Microsoft .NET Framework
   Microsoft ASP.NET
   정규식 API

요약: 정규식은 텍스트로 작업할 때 매우 유용한 도구입니다. 사용자 입력의 유효성을 검사해야 하거나, 문자열 내의 패턴을 검색해야 하거나, 효과적으로 텍스트 서식을 다시 지정해야 할 경우 정규식을 사용하면 좋습니다(14페이지/인쇄 페이지 기준).

이 기사의 소스 코드를 다운로드하십시오.

목차

소개
정규식 개요
단순식
한정사
메타 문자
문자 클래스
미리 정의된 메타 문자 집합
샘플 식
ASP.NET의 유효성 검사
정규식 API
무료 도구
고급 항목
결론
리소스
저자 소개

소개

Microsoft.NET Framework에서는 정규식을 완벽하게 지원하며, Microsoft ASP.NET 내에도 정규식 언어를 사용하는 컨트롤이 있습니다. 이 기사에서는 정규식의 기본 정보와 함께 자세한 내용을 참조할 수 있는 추가 정보를 다룹니다.

이 기사는 정규식에 대해서는 잘 몰라도 ASP.NET 및 .NET의 프로그래밍에는 익숙한 초급자를 위해 쓰여졌습니다. 이전에 정규식을 사용해 본 개발자들도 정규식 요약 과 함께 이 기사를 편리하게 참조하고 정보를 새롭게 상기할 수 있기를 바랍니다. 이 기사에서는 다음 내용을 다룹니다.

  1. 정규식 개요
  2. 단순식
  3. 한정사
  4. 메타 문자
  5. 문자 클래스
  6. 미리 정의된 메타 문자 집합
  7. 샘플 식 세부 정보
  8. ASP.NET의 유효성 검사
  9. 정규식 API
  10. 무료 도구
  11. 고급 항목 개요
  12. 요약 및 추가 리소스

이 기사나 정규식에 대한 일반적인 의문 사항이 있을 경우 350명 이상의 가입자를 보유한 http://www.aspadvice.com/ regex 메일 그룹 에서 질문하십시오.

정규식 개요

오늘날 사용되는 정규식은 1950대에 고안되었습니다. 원래 정규식은 신경 생리학자들의 연구 시 패턴이었던 "정규 집합"을 설명하는 데 사용되었습니다. 최초로 정규식을 만든 사람은 수학자 Stephen Kleene입니다. 이후에 Ken Thompson은 매우 일반적인 텍스트 유틸리티인 QED 및 GREP에 정규식을 도입했습니다. Jeffrey Friedl은 그의 저서 Mastering Regular Expressions(2판)에서 더 심도 있게 다루었습니다. 정규식의 이론과 개요에 대해 자세히 배우려는 분들께 이 책을 권장합니다.

지난 50년 동안 정규식은 불명확한 수학적 개념에서 많은 도구와 소프트웨어 패키지의 주요 기능으로 서서히 변화해 왔습니다. 수십 년 동안 많은 UNIX 도구에서 정규식을 지원했지만 정규식이 대부분의 Windows 개발자 도구 키트로서 제대로 자리잡기 시작한 것은 10년 정도 밖에 되지 않았습니다. Microsoft Visual Basic 6 또는 Microsoft VBScript에서는 정규식을 사용하기가 다소 불편했지만 새로 출시된 .NET Framework에서는 정규식을 완벽하게 지원하게 되어 모든 Microsoft 개발자가 모든 .NET 언어에 정규식을 사용할 수 있게 되었습니다.

그러면 정규식이란 무엇일까요? 정규식은 텍스트 문자열에서 패턴을 명시적으로 설명하는 데 사용할 수 있는 언어입니다. 이러한 패턴을 단순히 설명하는 것 외에도 일반적으로 정규식 엔진을 사용하면 일치 항목을 반복하거나 패턴을 구분 기호로 사용하여 문자열을 하위 문자열로 구문 분석하거나 지능적인 방식으로 텍스트를 바꾸거나 형식을 다시 지정할 수 있습니다. 또한 정규식을 사용하여 강력하고 간단한 방식으로 텍스트 처리와 관련된 많은 일반 작업을 해결할 수 있습니다.

정규식에 대해 설명할 때는 정규식과 일치하거나 일치하지 않는 텍스트를 기준으로 분석하는 것이 일반적입니다. 이 기사와 System.Text.RegularExpressions 클래스에서는 정규식 상호 작용의 3가지 항목인 정규식 패턴, 입력 문자열 및 패턴이 문자열 내에 만드는 일치에 대해 설명하도록 하겠습니다.

단순식

가장 단순한 정규식은 이미 친숙해 있는 정규식인 리터럴 문자열입니다. 특정 문자열을 문자 그대로 설명할 수 있으므로 foo와 같은 정규식 패턴은 입력 문자열 foo와 정확히 한 번 일치합니다. 이러한 경우 이 문자열은 The food was quite tasty 입력과도 일치합니다. 그러나 정확히 일치하는 항목만 찾을 경우 이 입력을 원하지 않을 수 있습니다.

물론 자신과 정확히 일치하는 문자열을 찾는 것은 일반적인 정규식 구현의 결과일 뿐 강력한 기능이라고 말할 수는 없습니다. foo 대신 f로 시작하는 모든 단어를 찾으려는 경우 또는 3자로 된 단어를 찾으려는 경우는 어떨까요? 이 정도 조건이라면 이미 리터럴 문자열로 수행할 수 있는 작업의 범위는 넘어 선 것입니다. 이제 정규식에 대해 더 자세히 배워야 합니다. 다음은 샘플 리터럴 표현식 및 일치하는 일부 입력입니다.

패턴 입력(일치 항목)
foo foo, food, foot, "There's evil afoot."

한정사

한정사를 사용하면 패턴 내에 특정 문자 또는 문자 집합을 반복할 수 있는 횟수를 간단히 지정할 수 있습니다. 다음과 같은 3가지 비명시적 한정사가 있습니다.

  1. *는 "0개 이상의 항목"을 나타냅니다.
  2. +는 "1개 이상의 항목"을 나타냅니다.
  3. ?는 "0개 또는 1개의 항목"을 나타냅니다.

한정사는 항상 한정사 바로 앞(왼쪽)에 있는 패턴을 참조합니다. 패턴 그룹을 만드는 데 괄호가 사용되지 않은 경우 이 한정사는 일반적으로 단일 문자입니다. 다음은 몇 가지 샘플 패턴 및 일치하는 입력입니다.

패턴 입력(일치 항목)
fo* foo, foe, food, fooot, "forget it", funny, puffy
fo+ foo, foe, food, foot, "forget it"
fo? foo, foe, food, foot, "forget it", funny, puffy

주어진 패턴이 정확히 0번 또는 한 번 발생할 수 있도록 지정하는 것 외에도 ? 문자는 입력 문자열에서 여러 개가 일치할 수 있을 경우 패턴 또는 하위 패턴이 최소 문자 수와 일치하도록 지정합니다.

비명시적 한정사(일반적으로 간단히 한정사라고 하지만 다음 그룹과 구분하기 위함) 외에도 명시적 한정사가 있습니다. 한 가지 패턴으로 발생할 수 있는 횟수와 관련하여 한정사가 모호할 경우 명시적 한정사를 사용하면 정확한 수, 범위 또는 숫자 집합을 지정할 수 있습니다. 정규 한정사와 같이 명시적 한정사는 적용되는 패턴 다음에 위치합니다. 명시적 한정사는 중괄호{} 및 숫자 값을 사용하여 이 괄호 안에 상한 및 하한 발생 수를 지정합니다. 예를 들어 x{5}는 x 문자 5개(xxxxx)와 일치합니다. 숫자 한 개만 지정한 경우 x{5,}와 같이 뒤에 쉼표를 입력하지 않는 한 상한으로 사용됩니다(개수에 상관없이 4개 이상의 x 문자와 일치).

패턴 입력(일치 항목)
ab{2}c abbc, aaabbccc
ab{,2}c ac, abc, abbc, aabbcc
ab{2,3}c abbc, abbbc, aabbcc, aabbbcc

메타 문자

정규식에서 특별한 의미가 있는 구성을 메타 문자라고 합니다. 앞서*, ?, +, { } 문자 등의 여러 메타 문자에 대해 이미 살펴 보았습니다. 기타 여러 문자는 정규식의 언어로 특별한 의미가 있습니다. 이러한 문자에는 $ ^ . [ ( | ) ] \ 등이 있습니다.

.(마침표 또는 점) 메타 문자는 가장 단순하면서도 가장 많이 사용되는 문자 중 하나입니다. 이 문자는 어떤 단일 문자와도 일치하며, 특정 패턴에 문자 조합이 포함될 수 있지만 한정사를 사용하여 특정 길이 범위 내에 속하도록 지정하는 데 유용합니다. 또한 긴 문자열 내에서 설명하는 패턴의 인스턴스에 식이 일치하는 것도 살펴 보았습니다. 그러나 패턴과 정확히 일치하도록 하려면 어떻게 해야 할까요? 이러한 경우는 우편 번호나 전화 번호에 적합한 형식으로 입력했는지 확인하는 경우와 같이 유효성 검사 시나리오에 자주 일어납니다. ^ 메타 문자는 문자열 또는 줄의 처음을 지정하는 데 사용되며 $ 메타 문자는 문자열이나 줄의 끝을 지정하는 데 사용됩니다. 이러한 문자를 패턴의 처음과 끝에 추가하면 패턴에 정확히 일치하는 입력 문자열에만 일치하도록 할 수 있습니다. 또한 ^ 메타 문자는 대괄호 [ ]로 지정되는 문자 클래스의 처음에 사용될 경우 특별한 의미가 있습니다. 이 내용은 아래에서 설명하겠습니다.

\(백슬래시) 메타 문자는 문자가 특별한 의미를 가지지 않도록 하는 데 사용되며 미리 정의된 메타 문자 집합의 인스턴스를 지정하는 데 사용됩니다. 이 내용도 아래에서 설명하겠습니다. 정규식이 메타 문자의 리터럴 버전을 포함하도록 하려면 백슬래시를 사용하여 특정 의미를 해제해야 합니다. 그러므로 인스턴스에 대해 "c:\"로 시작하는 문자열과 일치시키려는 경우 ^c:\\를 사용할 수 있습니다. 여기서 ^ 메타 문자를 사용하여 문자열이 이 패턴으로 시작되도록 지정했으며 백슬래시 메타 문자를 사용하여 리터럴 백슬래시를 해제했다는 점에 유의하십시오.

|(파이프) 메타 문자는 교체에 사용되며 기본적으로 패턴에서 'A 또는 B'를 지정합니다. 그러므로 a|b와 같은 입력은 'a' 또는 'b'가 포함된 어떤 내용에도 일치하며 문자 클래스 [ab]와 매우 비슷합니다.

마지막으로, 괄호 ( )는 패턴을 그룹화하는 데 사용됩니다. 가독성만을 위해 한정사를 사용하여 전체 패턴이 여러 번 발생하도록 허용하거나 입력의 특정 부분이 개별적으로 일치하도록 하여 서식을 다시 지정하거나 구문 분석을 수행하기 위해 패턴을 그룹화할 수 있습니다.

다음은 메타 문자 사용의 예를 보여 줍니다.

패턴 입력(일치 항목)
. a, b, c, 1, 2, 3
.* Abc, 123, 모든 문자열, 심지어 문자가 없어도 일치
^c:\\ c:\windows, c:\\\\\, c:\foo.txt, c:\ 다음에 오는 임의의 문자
abc$ abc, 123abc, abc로 끝나는 모든 문자열
(abc){2,3} abcabc, abcabcabc

문자 클래스

문자 클래스는 대괄호 [ ]로 둘러 쌓여 정의되는 것으로, 정규식 내의 소언어입니다. 가장 단순한 문자 클래스는 [aeiou]와 같이 단순히 괄호 안에 있는 문자 목록입니다. 식 안에 사용할 경우 이러한 문자 중 하나를 패턴 내의 이 위치에 사용할 수 있습니다. 그러나 한정사를 사용하지 않을 경우에 한하여 한 번만 사용할 수 있습니다. 문자 클래스를 사용할 경우 단어나 패턴은 정의할 수 없으며 단일 문자만 정의할 수 있습니다.

숫자를 지정하려면 문자 클래스 [0123456789]를 사용할 수 있습니다. 그러나 이렇게 길게 쓰면 오히려 사용하기 불편할 수 있으므로 하이픈 문자(-)를 사용하여 괄호 안에 문자 범위를 정의할 수 있습니다. 이 하이픈 문자는 문자 클래스에서만 특별한 의미가 있을 뿐 정규식에서는 별다른 의미가 없으므로 정규식 메타 문자로 정확히 한정하지는 않습니다. 또한 문자 클래스에서도 첫 문자가 아닌 경우에만 특별한 의미가 있습니다. 하이픈을 사용하여 숫자를 지정하려면 [0-9]를 사용합니다. 마찬가지로 소문자의 경우 [a-z]를 사용하고 대문자의 경우 [A-Z]를 사용하면 됩니다. 하이픈으로 정의되는 범위는 사용 중인 문자 집합에 따라 다르므로 ASCII 또는 유니코드 테이블 등에서의 문자 순서는 해당 범위에 포함되는 문자를 결정합니다. 범위에 하이픈을 포함해야 할 경우에는 첫 문자로 지정합니다. 예를 들어 [-.? ]는 이 4개 문자 중 하나와 일치합니다(마지막 문자는 공백). 또한 정규식 메타 문자는 문자 클래스 내에서 특별하게 처리되지 않으므로 의미를 해제할 필요가 없습니다. 문자 클래스는 고유 규칙과 구문을 사용하므로 나머지 정규식과는 다른 별도의 언어로 간주해야 합니다.

또한 문자 클래스에서 캐럿(^)을 첫 문자로 사용하여 문자 클래스를 빼면 문자 클래스의 구성원을 제외하고 임의의 문자를 일치시킬 수 있습니다. 그러므로 모음이 아닌 문자를 일치시키려면 [^aAeEiIoOuU]와 같은 문자 클래스를 사용할 수 있습니다. 하이픈을 빼려는 경우 [^-]과 같이 문자 클래스에서 두 번째 문자로 입력해야 합니다. 문자 클래스에서 ^ 문자는 정규식 패턴의 첫 문자로 사용할 때와 전혀 다른 의미를 가진다는 점에 유의하십시오.

다음은 사용 중인 문자 클래스의 예를 보여 줍니다.

패턴 입력(일치 항목)
^b[aeiou]t$ Bat, bet, bit, bot, but
^[0-9]{5}$ 11111, 12345, 99999
^c:\\ c:\windows, c:\\\\\, c:\foo.txt, c:\ 다음에 오는 임의의 문자
abc$ abc, 123abc, abc로 끝나는 모든 문자열
(abc){2,3} abcabc, abcabcabc
^[^-][0-9]$ 0, 1, 2, … (-0, -1, -2 등과 일치하지 않음)

다음 버전의 .NET Framework에서 새 기능인 코드 이름 "Whidbey"가 문자 클래스 빼기라는 문자 클래스에 추가될 예정입니다. 기본적으로 이 기능을 사용하면 한 문자 클래스에서 다른 문자 클래스를 뺄 수 있으므로 일부 패턴을 보다 편리하게 설명할 수 있습니다. 이 지정 사항은 현재 http://www.gotdotnet.com/team/clr/bcl/TechArticles/techarticles/Specs/Regex/CharacterClassSubtraction.doc 에서 볼 수 있습니다. 모든 소문자와 일치하는 구문은 [a-z-[aeiou]]와 같습니다.

미리 정의된 메타 문자 집합

지금까지 설명한 도구를 사용하여 수많은 작업을 수행할 수 있습니다. 그러나 패턴에서 모든 숫자에 대해 [0-9]라고 사용하는 것도 길다고 볼 수 있으며 영숫자 문자에서 [0-9a-zA-Z]와 같이 사용할 경우에는 더 불편합니다. 이와 같이 일반적이지만 매우 긴 패턴의 불편함을 없애기 위해 메타 문자 집합을 미리 정의했습니다. 정규식을 다르게 구현하면 미리 정의된 메타 문자 집합도 다르게 정의됩니다. 여기서 설명하는 메타 문자 집합은 .NET Framework의 System.Text.RegularExpressions API에서 지원됩니다. 미리 정의된 이러한 메타 문자의 표준 구문은 백슬래시(\) 다음에 하나 이상의 문자를 입력하는 것입니다. 대부분의 미리 정의된 메타 문자 길이는 문자 하나이므로 쉽게 사용할 수 있고 긴 문자 클래스 대신에 편리하게 사용할 수 있습니다. 두 가지 예로, 임의의 숫자와 일치하는 \d와 단어 문자(영숫자와 밑줄)와 일치하는 \w가 있습니다. 유니코드 캐리지 리턴 문자와 일치하는 \u000D와 같이, 일치하는 문자의 주소를 지정해야 하는 특수 문자 코드 일치는 예외입니다. 가장 일반적으로 사용하는 문자 클래스와 해당 메타 문자는 다음과 같습니다.

메타 문자 해당 문자 클래스
\a 벨(경보)과 일치합니다. \u0007
\b 문자 클래스 안에 사용되는 경우를 제외하고 단어 경계와 일치합니다. 백슬래시 문자 \u0008과 일치합니다.
\t 탭과 일치합니다. \u0009
\r 캐리지 리턴과 일치합니다. \u000D
\w 세로 탭과 일치합니다. \u000B
\f 용지 공급과 일치합니다. \u000C
\n 새 행과 일치합니다. \u000A
\e 이스케이프와 일치합니다. \u001B
\040 세 자리 8진수를 사용하는 ASCII 문자와 일치합니다. \040은 공백을 나타냅니다(십진수 32).
\x20 두 자리 16진수를 사용하는 ASCII 문자와 일치합니다. 이 경우 \x2-는 공백을 나타냅니다.
\cC ASCII 컨트롤 문자와 일치합니다. 이 경우 ctrl-C입니다.
\u0020 정확히 4자리 16진수를 사용하는 유니코드 문자와 일치합니다. 이 경우 \u0020은 공백입니다.
\* 미리 정의된 문자 클래스를 나타내지 않는 문자는 단순히 해당 문자로 처리됩니다. 그러므로 \*\x2A와 같습니다(*는 메타 문자가 아니라 리터럴임).
\p{name} 명명된 문자 클래스 'name'에 있는 임의의 문자와 일치합니다. 지원되는 이름은 유니코드 그룹 및 블록 범위입니다. 예를 들어 Ll, Nd, Z, IsGreek, IsBoxDrawing 및 Sc(통화)와 같습니다.
\P{name} 명명된 문자 클래스 'name'에 포함되지 않은 텍스트와 일치합니다.
\w 임의의 단어 문자와 일치합니다. 비유니코드 및 ECMAScript 구현의 경우 [a-zA-Z_0-9]와 같습니다. 유니코드 범주에서는 [\p{Ll}\p{Lu}\p{Lt}\p{Lo}\p{Nd}\p{Pc}]와 같습니다.
\W \w를 빼고, ECMAScript 규격 집합 [^a-zA-Z_0-9] 또는 유니코드 문자 범주 [^\p{Ll}\p{Lu}\p{Lt}\p{Lo}\p{Nd}\p{Pc}]와 같습니다.
\s 공백 문자와 일치합니다. 유니코드 문자 클래스 [\f\n\r\t\v\x85\p{Z}]와 같습니다. ECMAScript 옵션을 사용하여 ECMAScript 규격 동작을 지정한 경우 \s는 [ \f\n\r\t\v](선행 공백이 있음)와 같습니다.
\S 공백이 아닌 문자와 일치합니다. 유니코드 문자 범주 [^\f\n\r\t\v\x85\p{Z}]와 같습니다. ECMAScript 옵션을 사용하여 ECMAScript 규격 동작을 지정한 경우 \S는 [^ \f\n\r\t\v](^ 다음에 공백이 있음)와 같습니다.
\d 십진수와 일치합니다. 유니코드의 경우 [\p{Nd}]와 같고, 비유니코드 ECMAScript 동작의 경우 [0-9]와 같습니다.
\D 십진수가 아닌 숫자와 일치합니다. 유니코드의 경우 [\P{Nd}]와 같고, 비유니코드 ECMAScript 동작의 경우 [^0-9]와 같습니다.

샘플 식

대부분의 경우 예를 들어 설명할 때 가장 효과적으로 이해할 수 있으므로 여기서 몇 가지 샘플 식을 보여 드리겠습니다. 더 많은 샘플 식을 보려면 온라인 정규식 라이브러리 http://www.regexlib.com/ 을 방문하십시오.

패턴 설명
^\d{5}$ 미국 우편 번호와 같은 5자리 숫자입니다.
^(\d{5})|(\d{5}-\d{4}$ 5자리 숫자 또는 5자리 숫자-대시-4자리 숫자입니다. 미국 우편 번호 또는 미국 우편 번호+4 형식과 일치합니다.
^(\d{5}(-\d{4})?$ 앞의 예와 같지만 더 효율적입니다. ?를 사용하면 교체를 통해 별도의 패턴 두 개를 개별적으로 비교해야 하는 대신에 패턴의 4자리 부분을 선택적으로 입력할 수 있습니다.
^[+-]?\d+(\.\d+)?$ 실수와 일치하며 선택적으로 기호를 사용할 수 있습니다.
^[+-]?\d*\.?\d*$ 위의 예와 같지만 빈 문자열에도 일치합니다.
^(20|21|22|23|[01]\d)[0-5]\d$ 24시간 값과 일치합니다.
/\*.*\*/ C 스타일 주석 /* … */의 내용과 일치합니다.

ASP.NET의 유효성 검사

ASP.NET에서는 이전 ASP(또는 클래식 ASP)를 사용할 때보다 훨씬 쉽게 웹 양식 입력의 유효성을 검사하는 유효성 검사 컨트롤 집합을 제공합니다. 가장 강력한 유효성 검사기 중 하나는 RegularExpressionValidator입니다. 이 검사기는 입력과 일치해야 하는 정규식을 제공하여 입력의 유효성을 검사할 수 있습니다. 정규식 패턴은 컨트롤의 ValidationExpression 속성을 설정하여 지정합니다. 다음은 우편 번호 필드의 유효성 검사기 예를 보여 줍니다.

<asp:RegularExpressionValidator runat="server" id="ZipCodeValidator" 
ControlToValidate="ZipCodeTextBox" ErrorMessage="잘못된 우편 번호입니다. 
format; format should be either 12345 or 12345-6789."  
ValidationExpression="(\d{5}(-\d{4})?" />(참고: 프로그래머 코멘트는 샘플 프로그램 파일에는 영문으로 제공되며 기사에는 설명을 위해 번역문으로 제공됩니다.)

다음은 RegularExpressionValidator에 대해 알아 두어야 할 사항입니다.

  • 유효성 검사 중인 컨트롤에서 빈 문자열로 활성화할 수 없습니다. RequiredFieldValidator에서만 빈 문자열을 인식합니다.
  • 문자열의 처음과 끝에 일치 문자 ^$가 가정되므로 따로 지정할 필요가 없습니다. 하지만 단지 불필요한 것일 뿐 이 문자를 추가해도 손상되거나 변경되는 것은 없습니다.
  • 모든 유효성 검사 컨트롤과 마찬가지로 이 유효성 검사는 클라이언트 쪽과 서버 쪽 모두에서 수행됩니다. 정규식이 ECMAScript 규격이 아닌 경우 클라이언트에서 실패합니다. 이 문제를 방지하려면 식이 ECMAScript 규격인지 확인하거나 서버에서만 유효성 검사를 수행하도록 컨트롤을 설정합니다.

정규식 API

ASP.NET 유효성 검사 컨트롤을 제외하고 .NET에서 정규식을 사용하는 대부분의 경우 System.Text.RegularExpressions 네임스페이스에 있는 클래스를 사용합니다. 특히 잘 알고 있어야 하는 주요 클래스는 Regex, MatchMatchCollection입니다.

중요하지 않은 문제이지만, 정규식의 약어인 regex를 /reg-eks/로 발음할 것인지 또는 /rej-eks/로 발음할 것인지에 관한 란이 있습니다. 개인적으로 후자를 선호하지만 두 가지 경우 모두 전문가들이 주장하고 있으므로 원하는 발음을 사용하면 됩니다.

Regex 클래스에는 풍부한 메서드와 속성이 있습니다. 이전에 이 클래스를 사용해 본 적이 없을 경우 약간 어렵다고 생각할 수도 있을 것입니다. 다음은 가장 자주 사용되는 메서드를 요약한 것입니다.

메서드 설명
Escape / Unescape 식에서 리터럴로 사용하기 위해 문자열에서 메타 문자 의미를 해제합니다.
IsMatch 입력 문자열에서 일치하는 항목을 찾을 경우 True를 반환합니다.
Match 입력 문자열에서 일치하는 항목을 찾을 경우 Match 개체를 반환합니다.
Matches 입력 문자열에서 찾은 일치 항목이 모두 포함된 MatchCollection 개체를 반환합니다.
Replace 입력 문자열에서 일치하는 항목을 지정된 바꾸기 문자열로 바꿉니다.
Split 입력 문자열을 regex 일치 항목으로 구분하여 배열 요소로 나눔으로써 문자열 배열을 반환합니다.

많은 메서드 외에도, 주로 Regex 개체의 생성자에서 지정할 수 있는 수많은 옵션이 있습니다. 이러한 옵션은 비트 마스크의 일부이므로 OR를 사용할 수 있습니다. 즉, Multiline과 Singleline을 동시에 사용할 수 있습니다.

옵션 설명
Compiled 루프에서 많은 일치 작업을 수행할 경우 이 옵션을 사용합니다. 이 옵션을 사용하면 각 반복 작업에서 식의 구문 분석 단계를 줄일 수 있습니다.
Multiline 입력 문자열에 몇 줄이 있는지와 아무 상관이 없습니다. 오히려 이 옵션은 단순히 ^$의 동작을 수정하므로 전체 입력 문자열의 시작과 끝 대신 BOL 및 EOL과 일치합니다.
IgnoreCase 패턴에서 검색 문자열을 일치시킬 때 대/소문자를 무시합니다.
IgnorePatternWhitespace 패턴에 원하는 수만큼 공백을 넣을 수 있으며 (?# comment #) 구문을 사용하여 패턴 내 주석을 사용할 수 있게 합니다.
SingleLine 입력 문자열에 몇 줄이 있는지와 아무 상관이 없습니다. 오히려 .(마침표) 메타 문자가 \n을 제외하고 모든 문자와 일치(기본값)하는 대신, 임의의 문자와 일치하도록 만듭니다.

정규식을 사용할 수 있는 몇 가지 일반적인 작업에는 유효성 검사, 일치 및 바꾸기가 있습니다. 대부분의 경우 이 작업은 Regex 클래스의 정적 메서드를 사용하여 수행할 수 있으며 Regex 클래스 자체를 인스턴스화할 필요가 없습니다. 유효성 검사를 수행하려면 올바른 식을 만들거나 찾아서 Regex 클래스의 IsMatch() 메서드를 사용하여 입력 문자열에 적용하기만 하면 됩니다. 예를 들어 다음 함수는 정규식을 사용하여 우편 번호의 유효성을 검사하는 방법을 보여 줍니다.

private void ValidateZipButton_Click(object sender, System.EventArgs e)
{
   String ZipRegex = @"^\d{5}$";
   if(Regex.IsMatch(ZipTextBox.Text, ZipRegex))
   {
      ResultLabel.Text = "우편 번호가 유효합니다!";
   }
   else
   {
      ResultLabel.Text = "우편 번호가 잘못되었습니다!";
   }
}

마찬가지로, 다음과 같이 정적 Replace() 메서드를 사용하여 일치하는 항목을 특정 문자열로 바꿀 수 있습니다.

String newText = Regex.Replace(inputString, pattern, replacementText);

마지막으로, 다음과 같은 코드를 사용하여 입력 문자열에서 일치하는 항목 집합을 반복할 수 있습니다.

private void MatchButton_Click(object sender, System.EventArgs e)
{
   MatchCollection matches = Regex.Matches(SearchStringTextBox.Text, 
MatchExpressionTextBox.Text);
   MatchCountLabel.Text = matches.Count.ToString();
   MatchesLabel.Text = "";
   foreach(Match match in matches)
   {
      MatchesLabel.Text += "Found " + match.ToString() + " at 
position " + match.Index + ".<br>";
   }
}

기본 동작 외에 다른 동작을 지정해야 할 경우 일반적으로 Regex 클래스의 인스턴스를 인스턴스화해야 합니다. 특히 설정 옵션의 경우가 그렇습니다. 예를 들어 대/소문자와 패턴 공백을 무시하는 Regex 인스턴스를 만들고 해당 식에 대해 일치하는 항목 집합을 검색하려면 다음 코드를 사용합니다.

Regex re = new Regex(pattern, 
   RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
MatchCollection mc = re.Matches(inputString);

이 샘플의 전체 작업 버전은 다운로드한 이 기사에 단순 ASP.NET 페이지로 포함되어 있습니다.

무료 도구

Regulator(http://royo.is-a-geek.com/iserializable/regulator/ ) - 클라이언트 쪽에서 실행하도록 만들어진 정규식 테스트 도구로서, 웹 서비스를 통해 RegexLib과 통합되며 일치, 분할, 바꾸기 등을 지원합니다. 성능 분석 및 구문 강조가 포함됩니다.

RegexDesigner.NET(http://www.sellsbrothers.com/tools/ ) - 정규식을 구성하고 테스트할 수 있는 강력한 비주얼 도구입니다. C# 및/또는 VB.NET 코드 및 컴파일된 어셈블리를 생성하여 식을 응용 프로그램에 쉽게 통합할 수 있게 합니다.

Regular Expression Workbench v2.0(http://www.gotdotnet.com/Community/UserSamples/Details.aspx?SampleGuid=C712F2DF-B026-4D58-8961-4EE2729D7322 ) - 정규식을 만들고 테스트하고 연구할 수 있는 Eric Gunnerson의 도구입니다. 마우스로 regex를 가리켜 그 의미를 디코딩할 수 있는 "Examine-o-matic" 기능이 들어 있습니다.

고급 항목

여기서 주목할 만한 두 가지의 정규식 기능은 명명된 그룹 및 둘러보기 처리(lookaround processing)입니다. 하지만 이 두 가지 항목은 자주 사용되는 것이 아니므로 여기서는 간략하게만 설명하겠습니다.

명명된 그룹을 사용할 경우 일치하는 개별 그룹에 이름을 지정하고 식 내에서 프로그래밍 방식으로 이러한 그룹을 참조할 수 있습니다. 입력 문자열에서 요소의 순서와 배치를 다시 정렬하여 입력 문자열의 서식을 바꿀 때 Replace 메서드와 함께 사용하면 특히 유용합니다. 예를 들어 MM/DD/YYYY 문자열 형식으로 지정된 날짜를 DD-MM-YYYY 형식으로 바꾸려는 경우를 가정해 봅니다. 첫 번째 형식을 캡처하고 해당 Matches 컬렉션을 반복한 다음 문자열 처리를 사용하는 식을 써서 바꾸기 문자열을 만들 수 있습니다. 이 식에는 어느 정도의 코드 및 처리가 필요합니다. 명명된 그룹을 사용하여 이와 같은 작업을 수행할 수 있습니다.

String MDYToDMY(String input)
{
   return Regex.Replace(intput, @"\b(?<month>\d{1,2})/(?<day>\d{1,2}/(?<year>\d{4})\b", "${day}-
${month}-${year}");
}

또한 이름뿐 아니라 번호로도 그룹을 참조할 수 있습니다. 모든 이벤트에서 이러한 참조를 역참조라고 합니다. 또한 일반적으로 역참조는 반복되는 문자를 찾기 위한 [a-z]\1 식과 같이 일치하는 식 자체 내에서 많이 사용됩니다. 이 식은 'aa', 'bb', 'cc' 등과는 일치하지만 'ab', 'ac' 등 모든 두 글자 조합에 해당하거나 이를 허용하는 [a-z]{2} 또는 [a-z][a-z]와는 다릅니다. 역참조를 사용하면 식에서 이미 구문 분석하고 일치시킨 입력 문자열의 일부에 대해 기억할 수 있습니다.

"둘러보기 처리"는 많은 정규식 엔진에서 지원하는 긍정적, 부정적 예측 및 분석 기능을 참조합니다. 모든 정규식 엔진에서 둘러보기 처리의 모든 변형을 지원하는 것은 아닙니다. 이 구성은 문자와 일치할 수 있지만 문자를 사용하지는 않습니다. 일부 패턴은 둘러보기 처리를 사용하지 않고 설명할 수 없습니다. 특히 패턴 일부의 존재가 다른 부분의 존재에 따라 결정되는 경우에는 더욱 그렇습니다. 각 둘러보기 기능의 구문은 다음과 같습니다.

구문 설명
(?=…) 긍정적 예측(Positive Lookahead)
(?!...) 부정적 예측(Negative Lookahead)
(?<=…) 긍정적 분석(Positive Lookbehind)
(?<!...) 부정적 분석(Negative Lookbehind)

둘러보기 처리를 사용해야 하는 경우의 예로는 암호 유효성 검사가 있습니다. 적어도 숫자가 하나 이상 포함된 4자에서 8자 사이의 암호를 입력해야 하는 암호 제한을 가정해 봅니다. 일치 항목에 대해 \d를 테스트하고 문자열 작업을 사용하여 길이를 테스트함으로써 이 작업을 수행할 수 있지만 정규식에서 전체를 수행하려면 둘러보기가 필요합니다. 다음 식이 나타내는 것과 같이 특히 긍정적 예측의 경우 더욱 그렇습니다. ^(?=.*\d).{4,8}$

결론

정규식을 사용하면 텍스트의 패턴을 효과적으로 설명할 수 있으므로 문자열 유효성 검사와 처리를 위한 리소스로 활용할 수 있습니다. .NET Framework는 System.Text.RegularExpressions 네임스페이스를 비롯하여, 특히 Regex 클래스에서 정규식을 완벽하게 지원합니다. API는 사용하기가 간편하지만 올바른 정규식을 사용하는 것이 때로는 어려운 일입니다. 다행히 정규식은 재사용률이 매우 높으며 많은 온라인 리소스에서 다른 사용자가 지정한 식을 찾아서 활용할 수도 있고, 만들기 어려운 정규식에 대해 도움도 받을 수 있습니다.

리소스

정규식 라이브러리 http://www.regexlib.com/ 

정규식 토론 목록 http://aspadvice.com/login.aspx?ReturnUrl=%2fSignUp%2flist.aspx%3fl%3d68%26c%3d16&l=68&c=16 

정규식 포럼 http://forums.regexadvice.com/ 

정규식 웹 로그 http://blogs.regexadvice.com/ 

Jeffrey Friedl의 Mastering Regular Expressions(O'Reilly) http://www.regex.info/ 

.NET 정규식 참조 http://msdn.microsoft.com/library/en-us/cpref/html/frlrfSystemTextRegularExpressions.asp 

Jscript 정규식 구문 http://www.msdn.microsoft.com/library/en-us/script56/html/js56jsgrpRegExpSyntax.asp 

정규식 정보 http://www.regular-expressions.info/ 

저자 소개

Microsoft ASP.NET MVP인 Steven A. Smith는 ASPAlliance.com 및 DevAdvice.com의 사장이자 소유자입니다. 또한 .NET 중심 교육 기관인 ASPSmith Ltd의 소유자이자 대표 강사로, MSDN 및 AspNetPRO 잡지에 실리는 기사뿐 아니라 ASP.NET Developer's Cookbook과 ASP.NET By Example 두 권의 책을 저술한 바 있습니다. 또한 매년 열리는 여러 회의에서 강연을 맡고 있고 INETA 강연자 협회의 회원이며, 경영학 석사 및 컴퓨터 과학 기술 학사 학위를 소지하고 있습니다.

전자 메일(ssmith@aspalliance.com)을 통해 저자와 연락할 수 있습니다.


Posted by 뭉치냐옹
: