technical notes

Tháng Chín 22, 2007

Các level transaction (IsolationLevel Enumeration)

Chuyên mục: Database — ngduy @ 8:44 sáng

Specifies the transaction locking behavior for the connection.

The IsolationLevel values are used by a .NET Framework data provider when performing a transaction.

The IsolationLevel remains in effect until explicitly changed, but it can be changed at any time. The new value is used at execution time, not parse time. If changed during a transaction, the expected behavior of the server is to apply the new locking level to all statements remaining.

Member name Description
Chaos The pending changes from more highly isolated transactions cannot be overwritten.
ReadCommitted Shared lock sẽ giữ khi data đang đọc để tránh dirty reads, nhưng data có thể thay đổi trước khi kết thúc một transaction. Kết quả là non-repeatable reads hay phantom data.
ReadUncommitted A dirty read is possible, meaning that no shared locks are issued and no exclusive locks are honored.
RepeatableRead Lock được đặt trên toàn data query, ngăn không cho người khác update data trong khi thực hiện transaction. Ngăn ngừa được việc đọc không liên tục nhưngphantom rows vẫn có thể xuất hiện.
Serializable A range lock đặt trong DataSet, không cho users khác update hay insert row vào dataset cho tới khi transaction complete.
Snapshot Giảm blocking bằng cách lưu 1 version của data để một ứng dụng có thể đọc trong khi một ứng dụng khác modify data. Trong một transaction đó sẽ không thể nhận được sự thay đổi data cho dù requery.
Unspecified A different isolation level than the one specified is being used, but the level cannot be determined.When using OdbcTransaction, if you do not set IsolationLevel or you set IsolationLevel to Unspecied, the transaction executes according to the default isolation level of the underlying ODBC driver.
 (Chỉ dịch trước chỗ nào quan trọng và sử dụng nhiều thôi.)

Tháng Chín 19, 2007

Exit sub vs Return in VB.NET

Chuyên mục: NET — ngduy @ 11:09 sáng

Hiện tại, sau khi search lung tung, chưa thấy sự khác nhau giữa Exit Sub và Return cho nên => Xài cái nào cũng được.

Tuy nhiên, vì exit sub cũ rồi, nên nếu xài thì cũng không hay lắm. Nên xài return cho nó mới mẻ. Chứ cũng chả ý nghĩa gì khác.

Tham khảo đây: http://www.ondotnet.com/pub/a/dotnet/excerpt/vbnetnut_appa/index.html?page=4

Tháng Chín 18, 2007

ClickOnce Deployment complete reference

Chuyên mục: Reference — ngduy @ 10:08 sáng

Tham khảo ClickOnce deployment toàn tập

http://msdn2.microsoft.com/en-us/library/t71a733d(VS.80).aspx

SQL Server 2005 Features Comparison

Chuyên mục: Reference — ngduy @ 9:50 sáng

Bảng so sánh các edition của SQL 2005 với nhau. Rất có ích khi lựa 1 bản để xài.

SQL Server 2005 Features Comparison

Customize Crystal Report data

Chuyên mục: Crystal Report — ngduy @ 7:11 sáng

1. Set database logon info:
There is 2 ways to set database logon info.
1. Using SetDatabaseLogon

rpt.SetDatabaseLogon(username, password, server, database)

However, sometime using SetDatabaseLogon won’t effect. At that time, uses TableLogOnInfo to apply logon info for each table in report source.

Dim t As New TableLogOnInfo
t.ConnectionInfo.UserID = AppSettingsInfo.GetDBUserSettings
t.ConnectionInfo.Password = AppSettingsInfo.GetDBPasswordSettings
t.ConnectionInfo.ServerName = AppSettingsInfo.GetDBHostSettings
rpt.Database.Tables(0).ApplyLogOnInfo(t)

2. Set record selection formula:

strWhere = "{ReportQuery.Column1} = " + strColumn1Condtion
strWhere = "{ReportQuery.Column2} = " & strColumn2Condtion
rpt.RecordSelectionFormula = strWhere

3. Set sort data:

rpt.DataDefinition.SortFields(0).Field = rpt.Database.Tables(0).Fields("Column1")
rpt.DataDefinition.SortFields(0).SortDirection = SortDirection.AscendingOrder

Pass Discrete Value in CR

Chuyên mục: Crystal Report — ngduy @ 4:59 sáng

Pass value for discrete parameter of crystal report in Visual Studio 2005.

DataTable dat;
CampaignListTableAdapter objAdpt = new CampaignListTableAdapter();
dat = objAdpt.GetCampaignList();
string strServerPath = Server.MapPath(".");
string strFullPath = Path.Combine(strServerPath, "RecentlySubmmited.rpt");

ReportDocument objReport = new ReportDocument();
objReport.Load(strFullPath);
objReport.SetDataSource(dat);

//Pass Discrete Value
ParameterDiscreteValue crValue = new ParameterDiscreteValue();
crValue.Value = "Recently Submitted";
ParameterFields objFields = objReport.ParameterFields;
objFields["Title"].CurrentValues.Add(crValue);

//Export to HTTP stream
objReport.ExportToHttpResponse(ExportFormatType.PortableDocFormat, Response, false, "RecentlySubmitted");

Freeze column in GridView

Chuyên mục: webform — ngduy @ 4:50 sáng

Add these styles into CSS

.Freezing
{
    position: relative;
    top: expression(this.offsetParent.scrollTop);
    z-index: 10;
}
.FreezingCol_Header
{
    position: relative;
    left: expression(document.getElementById("freezingDiv").scrollLeft);
    z-index: 1;
    border-top-width: 0px;
    border-left-width: 0px;
    border-right-width: 0px;
    border-bottom-width: 0px;
}
.FreezingCol_No
{
    position: relative;
    left: expression(document.getElementById("freezingDiv").scrollLeft);
    z-index: 1;
    border-top-width: 1px;
    border-left-width: 1px;
    border-right-width: 1px;
    border-bottom-width: 0px;
}
.FreezingCol_Item
{
    position: relative;
    left: expression(document.getElementById("freezingDiv").scrollLeft);
    z-index: 1;
    border-top-width: 1px;
    border-left-width: 0px;
    border-right-width: 1px;
    border-bottom-width: 0px;
}

How to uses?

Add GridView into div with specified ID freezingDiv

  • div id=”freezingDiv” style=”OVERFLOW-Y: visible; OVERFLOW: scroll; WIDTH: 300px; HEIGHT: 414px”

Using style for Header & Item

  • HeaderStyle CssClass=”FreezingCol_Header”
  • ItemStyle CssClass=”FreezingCol_Item” HorizontalAlign=”Center” BackColor=”White” BorderColor=”#666666″

* IE will response slowly when using this CSS. The best way is create another grid for static columns.

Restricting User Input using JavaScript and Reg Expressions

Chuyên mục: webform — ngduy @ 4:43 sáng
function keypress(cntrl)
{
   var cntrl1 = document.getElementById("Hidden1");
   cntrl1.value = cntrl.value;
}

function propertychanged(cntrl)
{
   //var reg = /^\\\\d+\\\\.?\\\\d{0,4}$/;
   var reg = /^[-]{1}$^[-]?([1-9]{1}[0-9]{0,11}(\\\\.[0-9]{0,4})?0(\\\\.[0-9]{0,4})?\\\\.[1-9]{1,4})$/;
   var val = cntrl.value;
   var cntrl1 = document.getElementById("Hidden1");
   var val1 = cntrl1.value;
   if (val.length > 0)
   {
      if (!reg.test(val))
      {
         cntrl.value = val1;
      }
   }
   else
   {
      cntrl1.value = "";
   }
}

Insert hidden field into aspx file and add attributes to TextBox

<asp:TextBox ID=”TextBox1″ runat=”server”
onkeypress=”keypress(this);” onpropertychange=”propertychanged(this);” ></asp:TextBox>
<input id=”Hidden1″ type=”hidden”>

We have 1 problem with Japanese (I’m not check with another), IE will crash when user input Hiragana or Full-size character into textbox. The simplest way is disable IME using CSS.
style=”text-align:right;ime-mode:disabled;”

Phát triển ứng dụng với SOA

Chuyên mục: NET — ngduy @ 4:38 sáng

SOA (Kiến trúc hướng dịch vụ) là từ được nhắc đến nhiều nhất trong năm qua, được hàng loạt công ty áp dụng và được bình chọn là công nghệ của năm 2006. SOA đang thay đổi cách thức phát triển các phần mềm ứng dụng cỡ lớn cho công ty. Chúng ta hãy cùng xem xét cách phát triển ứng dụng SOA trên nền NET.

1. Thiết kế.

Một ứng dụng hướng đối tượng thông thường gồm 3 lớp: Lớp Presentation đảm nhiệm việc hiển thị dữ liệu, lớp Business bao gồm các đối tượng thực thi các logic của chương trình, và lớp Data thực hiện nhiệm vụ kết nối cơ sở dữ liệu, các thao tác trực tiếp lên cơ sở dữ liệu. Việc tách riêng các lớp giúp cho việc quản lý và mở rộng chương trình được dễ dàng.Một thiết kế theo SOA không khác nhiều với ứng dụng hướng đối tượng, chỉ là sự thêm vào giữa lớp presentation và lớp Business 1 webservice có vai trò làm cầu nối. Lớp presentation không thao tác trực tiếp với lớp business nữa. Thay vì gọi trực tiếp một đối tượng, ứng dụng client gọi 1 dịch vụ.

Trong lập trình hướng đối tượng, lớp presentation có thể gọi nhiều đối tượng ở lớp bussiness, vì thế, mối liên hệ giữa lớp Presentation và lớp bussiness rất phức tạp. Một trong những điểm thay đổi của việc chuyển từ lập trình hướng đối tượng sang SOA là việc giảm thiểu sự liên kết giữa các đối tượng. Thiết kế ứng dụng với SOA giảm thiểu số lần gọi bằng cách đưa ra giao diện dịch vụ. Dịch vụ cung cấp một lớp trung gian làm giảm thiểu nhu cầu trao đổi giữa các lớp.

Vd 1 đoạn mã khi lập trình theo hướng đối tượng

public string OrderBookClient(String isbn)
{
    Book b = new book(isbn);
    OrderDetail od = new OrderDetail();
    od.add(b);
    Order o = new Order();
    o.add(od);
    o.save();
    return o.OrderNumber;
}

Đoạn mã trên khi được triển khai SOA

[WebMethod]
public string OrderBook(String isbn)
{
    Book b = new book(isbn);
    OrderDetail od = new OrderDetail();
    od.add(b);
    Order o = new Order();
    o.add(od);
    o.save();
    return o.OrderNumber;
}

Và tại ứng dụng client. Lời gọi dịch vụ sẽ được thực hiện 1 cách đơn giản.

public void OrderBookClient(String isbn)
{
         OrderService os = new OrderService();
         os.OrderBook(isbn);
}

Đây chỉ là 1 ví dụ mang tính tham khảo. Bạn phải thay đổi cách thức lập trình và thiết kế sao cho số lần gọi dịch vụ được hạn chế tối đa nhằm giảm sự hao tốn băng thông. Với các ứng dụng phân tán thông thường, chúng ta đã biết rằng tốt hơn là chuyển 1000 bytes 1 lần hơn là chuyển 1 byte và chuyển 1000 lần. Và điều này cũng vẫn đúng với các ứng dụng SOA.

2. Chuyển data giữa ứng dụng và service.

Việc chuyển data giữa service và application có thể thực hiện bằng nhiều cách. Có thể dùng DataSet, XML hay có thể chuyển cả object v.v… tuỳ thuộc vào thiết kế của bạn. Tuy nhiên, nếu triển khai SOA hoàn toàn trên NET, bạn nên xem xét việc thực hiện bằng DataSet. Có nhiều lý do bạn nên thực hiện bằng DataSet, đó là DataSet dễ dàng serialize (đã được hỗ trợ), khi chuyển data bằng DataSet, không phải tất cả object DataSet đó được chuyển qua SOAP mà chỉ data trong DataSet đó được chuyển. Ngoài ra, DataSet sẽ giúp bạn giảm thiểu việc phải lập trình lại giao diện Service nếu ứng dụng và service của bạn có thay đổi. Điều nên cân nhắc khi sử dụng DataSet là java không hiểu được DataSet nên nếu muốn Service phục vụ cho các ứng dụng viết bằng java, bạn sẽ gặp rất nhiều khó khăn khi phát triển.
Bạn cũng có thể sử dụng object, tuy nhiên, bạn phải chắc chắn rằng cả object có thể serialize. Các hàm và biến private không thể truy cập từ ứng dụng client là một trở ngại lớn khi dùng object.
Ngoài ra, còn một lựa chọn khác là XML. Tuy nhiên, nếu xây dựng ứng dụng SOA trên nền NET, hẳn nhiên là bạn sẽ mất nhiều thời gian cho việc thao tác với XML hơn là dùng DataSet.

3. Quản lý transaction

Có 2 cách để quản lý transaction. Quản lý transaction trong service và quản lý transaction trong ứng dụng client. Việc lựa chọn cách quản lý transaction của bạn tuỳ thuộc vào thiết kế của ứng dụng và dịch vụ.
Để quản lý transaction ở phía ứng dụng client. Các WebMethod phải được thiết lập để có thể hoạt động với Distributed Transaction Coordinator bằng cách thêm một thuộc tính vào method của WebService.

[WebMethod(TransactionOption=TransactionOption.RequiresNew)]

Việc quản lý transaction khi đó có thể thực hiện bình thường tại ứng dụng client thông qua TransactionScope.

4. Quản lý exception

Việc quản lý Exception trong ứng dụng SOA nên được quản lý chặt chẽ và hạn chế exception được ném ra từ các dịch vụ. Exception chỉ nên ném trong những trường hợp ngoại lệ có chủ ý và cần thiết phải ném Exception về phía client. Bạn không nên ném exception trong những trường hợp rẽ nhánh thông thường hoặc dùng exception để rẽ nhánh ứng dụng.
Các service khi ném Exception đến ứng dụng qua SOAP sẽ đều được chuyển thành SOAP Exception. Do đó, phía các ứng dụng client khi quản lý Exception cần bắt 3 loại Exception sau.

1. SoapException: Để bắt các exception của service ném ra.
2. WebException: Exception này xuất hiện khi gặp vấn đề về mạng như đường truyền v.v…
3. Exception phía ứng dụng: Các lỗi phát sinh trong ứng dụng client.

Theo kinh nghiệm cá nhân, bạn nên bắt tất cả exception của lớp bussiness và lớp data phía dịch vụ. Trong trường hợp bạn muốn hiển thị lỗi cho end user ở ứng dụng client, từ lớp dịch vụ, bạn ném 1 SOAPException cho ứng dụng client với một thông báo cụ thể cho trường hợp phát sinh lỗi. Nếu không, phía ứng dụng client bạn sẽ rất khó xác định được nguyên nhân chính của lỗi đã xảy ra phía dịch vụ.

5. Tổng kết

Ta có thể thấy phát triển ứng dụng SOA thực ra không khác nhiều so với việc phát triển ứng dụng hướng đối tượng. Chỉ đơn giản là thêm vào giữa lớp Bussiness và lớp Presentation một lớp mới, có tác dụng đưa Business thành 1 dịch vụ và lớp Presentation thành 1 ứng dụng độc lập, ở đó, mọi thao tác đều thông qua các dịch vụ tương ứng. Tuy nhiên, có thể thấy đây không chỉ là một mở rộng của lập trình hướng đối tượng mà là một sự thay đổi lớn trong kiến trúc. Các dịch vụ sẽ quản lý các thao tác với các đối tượng Business, dịch vụ sẽ hoạt động như một hộp đen, che đi những thao tác nghiệp vụ phức tạp.Một khác biệt dễ thấy nhất là lớp nghiệp vụ và lớp presentation sẽ độc lập với nhau.
Một lợi ích là các ứng dụng hướng dịch vụ sẽ gọi các dịch vụ khi cần thiết nên kết nối giữa ứng dụng và dịch vụ không cần “online” thường xuyên. Kết quả là giảm được rất nhiều băng thông và làm tăng tốc ứng dụng. Tuy nhiên, không hẳn SOA lúc nào cũng cần thiết. Đôi khi, việc phát triển ứng dụng theo lối “cổ điển” lại có ích cho bạn hơn. Điều đó tuỳ thuộc vào bạn.

Bài viết dựa theo quan điểm và kinh nghiệm cá nhân nên còn nhiều thiếu sót. Mong nhận được sự góp ý của tất cả các bạn.

Tháng Chín 17, 2007

Validate page before run a javascript code

Chuyên mục: webform — ngduy @ 11:09 sáng

By default, after we add an attributes for asp.net controls. javascript registered will be execute before validation. So. If we want to do something after validation., we should call Page_ClientValidate() to execute page validation.
Below is demo code:

        function confirmGoto(message)
        {
            if (Page_ClientValidate())
            {
                if (edited)
                {
                    var ok = confirm(message);
                    if(ok)
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
            }
        }
« Bài viết mới hơnBài viết cũ hơn »

Blog at WordPress.com.