technical notes

Tháng Mười 6, 2009

test

Chuyên mục: NET — ngduy @ 5:51 chiều

test

Tháng Bảy 22, 2009

Test

Chuyên mục: NET — ngduy @ 6:07 sáng

Test

Tháng Ba 9, 2008

.NET 2.0 Cast operator vs. As operator

Chuyên mục: NET — ngduy @ 6:23 chiều

Khi chuyển từ untyped data values từ SQL database vào 1 biến, sẽ có tình huống xảy ra, khi cast từ DBNull sang một kiểu nào đó, ta sẽ bị InvalidCastException. Tuy nhiên, có một cách để gán thoải mái mà không lo lắng gì. Bắt đầu xem ví dụ dưới đây:

object objstr = DBNull.Value;
string str1 = objstr; //Cast throws an Exception
string str2 = objstr as string //No exception thrown and str2 == null

Có thể dùng as để viết code cho gọn như vd dưới:

if ( objstr == DBNull.Value )
{
    strResult = "Default";
}
else
{
    strResult = (string)objstr;
}
//Is equivalent to
strResult = objstr as string ?? "Default";

Như vậy, as operator giống như cast operator, nhưng khi gặp null value, as sẽ chuyển giá trị thành null chứ không thrown exception như là cast.

Tham khảo MSDN C# Programmer’s Reference tại http://msdn2.microsoft.com/en-us/library/cscsdfbt(vs.71).aspx thì được giải thích như sau:

expression <span class="kwrd">as</span> type</pre>
<pre><span class="rem">//is equivalent to</span></pre>
<pre>expression <span class="kwrd">is</span> type ? (type)expression : (type)null

Fix wrong position of CalendarExtender

Chuyên mục: NET, webform — ngduy @ 5:59 chiều

Khi thêm CalendarExtender vào một số DataBound controls, thì xảy ra hiện tượng calendar hiển thị không đúng, tức là không hiển thị ngay phía dưới của Textbox. Sau đây là cách fix lỗi này:

Trang aspx:

<asp:TextBox ID="txtStartDate" runat="server"></asp:TextBox>
<asp:ImageButton ID="imgStartDate" ImageUrl="../images/calendar.gif" runat="server" CausesValidation="False" />
<ajaxToolkit:CalendarExtender id="CalendarExtender1" runat="server" TargetControlID="txtStartDate"
PopupButtonID="imgStartDate" CssClass="datePicker"></ajaxToolkit:CalendarExtender> 

Sau đó định nghĩa css này trong file stylesheet:

.datePicker

{
    position:relative;
    left:5px;
}

.datePicker .ajax__calendar_container
{
background-color:White!important;
border:1px solid blue!important;
z-index:50000;
}
.datePicker .ajax__calendar_hover .ajax__calendar_day
{background-color:#edf9ff;border-color:#daf2fc;color:#0066cc!important;}
.datePicker .ajax__calendar_hover .ajax__calendar_month
{background-color:#edf9ff;border-color:#daf2fc;color:#0066cc!important;}
.datePicker .ajax__calendar_hover .ajax__calendar_year
{background-color:#edf9ff;border-color:#daf2fc;color:#0066cc!important;}
.datePicker .ajax__calendar_hover .ajax__calendar_title
{color:#0066cc!important;}
.datePicker .ajax__calendar_hover .ajax__calendar_today
{color:#0066cc!important;}

Các style ở phía dưới có thể không có cũng được. Chủ yếu cho đẹp.

Tháng Mười 15, 2007

Huỷ biến trong .NET

Chuyên mục: NET — ngduy @ 9:46 sáng

Trong .NET environment, khi một object sẽ bị huỷ, bộ nhớ và resources nó dùng sẽ được thu hồi khi không còn tham chiếu nào đến object đó.

Khi dùng một object, biến sẽ giữ một tham chiếu hay con trỏ đến object đó.

Ví dụ

Dim myPerson As New Person()

Nghĩa là biến myPerson chỉ tham chiếu đến object vừa tạo. Nếu có đoạn code sau:

Dim anotherPerson As Person
anotherPerson = myPerson

Nghĩa là biến anotherPerson cũng tham chiếu đến cùng một object. Điều này có nghĩa là object Person thì được tham chiếu bởi 2 biến: myPerson và anotherPerson.

Khi không còn biến nào tham chiếu đến object, nó sẽ được .NET framework terminated. Cụ thể, nó sẽ được terminated và thu hồi bởi một cơ chế gọi là garbage collection.

Không giống COM (vd VB6), .NET framework không dùng cách đếm số tham chiếu để quyết định việc có huỷ object đó hay không. Thay vào đó, nó dùng một cơ chế khác để quyết định việc huỷ object đó.

Điều đó có nghĩa là, trong Visual Basic (hay .NET), ta không cần quyết định việc huỷ object đó, bởi vì không thể quyết định chính xác khi nào object sẽ được huỷ.

Để chấm dứt tham chiếu đến một object. Ta có thể gỡ tham chiếu một cách cụ thể bằng cách gán Nothing vào biến đó bằng đoạn code sau:

myPerson = Nothing

Ta cũng có thể gỡ bỏ tham chiếu tới một object bằng cách thay đổi tham chiếu của biến tới một object khác. Vì một biến chỉ có thể tham chiếu tới một object tại một thời điểm. Ta có thể code như sau:

myPerson = New Person()

Biến sẽ tham chiếu tới một object mới, vì thế, sẽ release tham chiếu tới object trước đó.

Đây là ví dụ về explicit dereferencing, VB còn cung cấp một phương pháp thuận tiện hơn để gỡ bỏ tham chiếu đến một object gọi là implicit dereferencing khi biến đó out of scope.

Ví dụ, nếu ta có một biến được mô tả trong một method, khi method hoàn tất, biến đó sẽ được tự động huỷ, như vậy cũng sẽ huỷ tham chiếu đến những object đã được tham chiếu.

Tóm lại, Bất cứ lúc nào biến tham chiếu đến một object out of scope, tham chiếu đến object đó sẽ tự động được huỷ. Ví dụ:

Private Sub DoSomething()
Dim myPerson As Person
myPerson = New Person()
End Sub

Cho dù ta không gán giá trị của myPerson là Nothing một cách cụ thể, ta biết rằng biến myPerson sẽ bị huỷ khi method kết thúc, sau khi nó out of scope. Tham chiếu đến Person object được tạo trong hàm sẽ hoàn toàn được gỡ bỏ.

Dĩ nhiên, sẽ có một kịch bản khác trong đó object sẽ bị huỷ khi ứng dụng hoàn toàn kết thúc. Vào lúc này, tất cả các biến sẽ bị huỷ, và tất cả tham chiếu đến object sẽ hoàn toàn kết thúc.

(Tham khảo: Wrox.Professional.VB.2005.Nov.2005.pdf – Chương 4, Trang 115)

Tháng Chín 24, 2007

Deploy to server using CLickOnce

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

Để deploy application lên server dùng ClickOnce. Server cần có

  • IIS
  • FrontPage 2002 Server Extensions.

Tuy nhiên, khi publish lên server, sẽ gặp những vấn đề sau:

Error 7 Failed to connect to ‘http://server IP/Projects/’ with the following error: Unable to create the Web ‘http://server IP/projects/’. Server error: Error 5 opening registry key “SOFTWARE\Classes”
=>
Do FrontPage server extensions không có quyền access vào key HKEY_LOCAL_MACHINE\SOFTWARE\Classes.
=>
  1. Vào regedit
  2. Nhấn phím phải lên HKEY_LOCAL_MACHINE\SOFTWARE\Classes. Chọn permissions
  3. Add user Everyone (Hiện tại chỉ biết add thế, cụ thể chỉ cần add user nào sẽ tìm hiểu sau)
  4. Check vào allow FullControl cho user Everyone
Error 7 Failed to connect to ‘http://server IP/Projects/’ with the following error: Unable to create the Web ‘http://server IP/projects/’. Server error: Error 5 opening registry key “SOFTWARE\Classes\.hlp”
=>
Nguyên nhân và cách khắc phục tương tự như trên.

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

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

Tắt office application sau khi quit (NET)

Chuyên mục: NET — ngduy @ 10:32 sáng

When you automate a Microsoft Office application from Microsoft Visual Basic .NET or Microsoft Visual C# .NET, the Office application does not quit when you call the Quit method.

To make sure that the Office application quits, make sure that your automation code meets the following criteria:

  • Use System.Runtime.InteropServices.Marshal.ReleaseComObject when you have finished using an object. This decrements the reference count of the RCW.
  • To release the reference to the variable, set the variable equal to Nothing or Null.
  • Use the Quit method of the Office application object to tell the server to shut down.
  Private Sub NAR(ByVal o As Object)
    Try
      System.Runtime.InteropServices.Marshal.ReleaseComObject(o)
    Catch
    Finally
      o = Nothing
    End Try
  End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Dim oApp As New Excel.Application()
    Dim oBooks As Excel.Workbooks = oApp.Workbooks
    Dim oBook As Excel.Workbook = oBooks.Add
    Dim oSheet As Excel.Worksheet = oApp.ActiveSheet

    NAR(oSheet)
    oBook.Close(False)
    NAR(oBook)
    NAR(oBooks)
    oApp.Quit()
    NAR(oApp)

    Debug.WriteLine("Sleeping...")
    System.Threading.Thread.Sleep(5000)
    Debug.WriteLine("End Excel")
End Sub

C#

private void NAR(object o)
{
    try
    {
        System.Runtime.InteropServices.Marshal.ReleaseComObject(o);
    }
    catch {}
    finally
    {
        o = null;
    }
}

Troubleshooting
Note that if you follow the steps that are described in the “Steps to Reproduce the Behavior” section, and the server still does not shut down, you can use the GC.Collect() method and the GC.WaitForPendingFinalizers() method after you release the last object. Because the runtime performs garbage collection on the RCW, the GC.Collect() method forces the garbage collector to run and might release any references that the RCW still has. The GC.Collect() method tries to reclaim the maximum memory that is available. Note that this does not guarantee that all memory will be reclaimed.

Blog at WordPress.com.