[Discovery] Tìm hiểu dòng máy bay Boeing 777

banner. ​

Boeing 777 là dòng máy bay đường dài 2 động cơ thân rộng được phát triển và chế tạo bởi BoeingCommercial Airplanes. Máy bay có sức chứa từ 314 đến 451 hành khách và có tầm bay từ 9.695 tới 17.372 km. Các đặc điểm nổi bật của Boeing gồm hệ thống càng hạ cánh 6 bộ lốp, động cơ phản lực cánh quạt đường kính lớn nhất, có thiết kế mặt cắt ngang thân dạng tròn và đuôi vuốt nhọn.

Dựa trên ý kiến của 8 hãng hàng không lớn, Boeing 777 được thiết kế nhằm thay thế cho các máy bay dân dụng thân rộng trước đó. Đồng thời 777 cũng đóng vai trò làm cầu nối thu hẹp sự khác biệt giữa Boeing 767 và 747. Boeing 777 là máy bay đầu tiên của Boeing được trang bị hệ thống điều khiển điện tử (fly by wire). Đây cũng là chiếc máy bay thương mại đầu tiên được thiết kế hoàn toàn bằng máy tính.

800px-Transaero_777-200ER_flight_deck.
Buồng lái nhìn từ bên trong Boeing 777-200ER.

Tính đến năm 2014, dòng Boeing 777 được sản xuất với 2 độ dài thân khác nhau. Phiên bản gốcBoeing 777-200 được chính thức hoạt động thương mại vào năm 1995, tiếp theo đó là phiên bản mở rộng 777-200ER vào năm 1997. Phiên bản tiếp theo là 777-300 với chiều thân máy bay dài hơn 10,1 mét được chính thức bay thương mại vào năm 1998. Các biến thể 777-300ER và 777-200LR bắt đầu sử dụng vào năm 2004 và 2006. Bên cạnh đó, 777 cũng có phiên bản máy bay chuyên chở hàng hóa là 777F ra mắt hồi tháng 2 năm 2009.

Các phiên bản bắt đầu từ năm 2004 đều được trang bị động cơ General Electric GE90. Trong khi đó, các phiên bản trước là 777-200, 77-200ER và 777-300 được trang bị động cơ 800 GE90, Pratt & Whitney PW4000 hoặc Rolls-Royce Trent. Hiện tại, 777-200LR là chiếc máy bay có tầm bay dài nhất thể giới với khả năng bay hơn nửa vòng Trái Đất trong 1 chuyến bay duy nhất.


Video cất cánh của 1 chiếc 777​

Vào tháng 11 năm 2013, Boeing tuyên bố đang phát triển phiên bản nâng cấp là 777-8X và 777-9X có cánh bằng vật liệu composite và động cơ GE9X.

United Airlines là hãng hàng không đầu tiên đặt hàng Boeing 777 nhằm khai thác thương mại vào tháng 6 năm 1995. Tính tới tháng 6 năm 2013, 60 khách hàng đã đặt 1452 chiếc Boeing mọi phiên bản và đã có 1113 chiếc được bàn giao. Phiên bản phổ biến và thành công nhất là 777-300ER với hơn 700 đơn đặt hàng và 452 chiếc đã được giao tính tới tháng 12 năm 2013.

Emirrates là hãng hàng không có số lượng Boeing 777 nhiều nhất với 127 chiếc chở khách và chuyên chở hàng hóa. Boeing 777 được đánh giá là 1 trong những dòng máy bay an toàn nhất dựa trên số lần gặp tai nặn và tổng số giờ bay an toàn.

Tính đến tháng 3 năm 2014, chỉ mới có 4 vụ tai nạn máy bay có liên quan trực tiếp tới Boeing 777 và Asiana Airlines Flight 214 là vụ tai nạn có thiệt hại về người đầu tiên trong 19 năm hoạt động thương mại của Boeing 777.

Boeing 777 cũng được xếp vào danh sách máy bay bán chạy nhất của Boeing do có mức tiêu thụ nhiên liệu hiệu quả và có tầm bay dài hơn so với các máy bay phản lực thân rộng khác. Đối thủ cạnh tranh trực tiếp của Boeing 777 là A330-300 của Airbus và sắp tới sẽ là A350 XWB.


Boeing 777 đang hạ cánh ghi lại tai sân bay L.A, Mỹ​

Quá trình phát triển

Bối cảnh hình thành

Từ đầu những năm 1970, Boeing 777, McDonnell Douglas DC-10 và Lockheed L-1011 TriStar là thế hệ máy bay thân rộng đầu tiên được khai thác thương mại. Năm 1978, Boeing giới thiệu mẫu mới: máy bay phản lực 2 động cơ Boeing 757 để thay thế cho Boeing 727, máy bay 2 động cơ Boeing 767 để cạnh tranh với Airbus A300 và mô hình máy bay 3 động cơ 777 để cạnh tranh với DC-10 và L-1011. Sau đó, các máy bay cỡ trung Boeing 757 và 767 chính thức được thương mại hóa thành công 1 phần nhờ vào các quy định ETOPS (tiêu chuẩn phạm vi hoạt động mở rộng của máy bay 2 động cơ) được Chính phủ Mỹ ban hành vào những năm 1980.

800px-All_Nippon_Airways_B777-300ER_JA784A.
1 chiếc Boeing 777-300ER của hãng hàng không Nippon vừa mới cất cánh​

Dựa trên quy định ETOPS, các hãng hàng không đã có thể mở các tuyến bay đường dài vượt đại dương bằng máy bay Boeing 767. Sau đó, dự án chế tạo mẫu máy bay 3 động cơ Boeing 777 bị hủy bỏ và chuyển sang các biến thể của dòng 757 và 767 do được thị trường ưa chuộng hơn. Sự hủy bỏ này đã làm cho 767-300ER à 747-400 có 1 khoảng cách lớn về kích cỡ và tầm bay.

Đến cuối những năm 1980, DC-10 và L-1011 đã không còn đáp ứng được nhu cầu sử dụng và các nhà sản xuất phải phát triển những mẫu máy bay mới để thay thế. McDonnell Douglas đã phát triển thế hệ máy bay MD-11, 1 người kế vị của DC-10 với kích thước kéo dài cùng với các nâng cấp khác. Trong khi đó, Airbus đang tập trung phát triển A330 và A340.

800px-Air_France_Boeing_777-228ER_F-GSPE_Kustov_planform.
Hình ảnh nhìn từ dưới của Boeing 777-200ER​

Năm 1986, Boeing đề xuất thế hệ máy bay hậu duệ của 767 mang tên 767-X nhằm cạnh tranh với máy bay thân rộng DC-10 đồng thời bổ sung cho các dòng trước đó của hãng là 767 và 747. Đề xuất thiết kế ban đầu là mẫu máy bay có thân và cánh dài hơn so với 767 và bổ sung thêm đầu cánh winglet. Sau đó, dự án đề nghị mở rộng mặt căt ngang thân máy bay nhưng vẫn giữ nguyên kích thước sàn, mũi và các yếu tố khác trên 767.

Tuy nhiên, các hãng hàng không đã không ấn tượng với mẫu 767-X nói trên. Thay vào đó, họ muốn có 1 chiếc máy bay với mặt cắt ngang thân lớn hơn, các thiết lập nội thất hoàn toàn linh hoạt, khả năng hoạt động liên lục địa và có động cơ hiệu suất cao hơn so với 767

Năm 1988, Boeing nhận thấy rằng câu trả lời duy nhất đáp ứng các yêu cầu của khách hàng chính là 1 máy bay với thiết kế hoàn toàn mới – máy bay phản lực 2 động cơ Boeing 777. Dưới sự đóng góp ý kiến của 8 hãng hàng không trong quá trình hình thành ý tưởng phát triển, Boeing gọi 777 là dòng máy bay có tính định hướng khách hàng nhất cho đến hiện nay.

Giai đoạn thiết kế:

Tại cuộc gặp gỡ đầu tiên với 8 khách hàng, Boeing đã cung cấp 1 bảng câu hỏi 23 trang để thăm dò các yêu cầu của khách hàng đối với mẫu máy bay mới. Đến tháng 3 năm 1990, Boeing và các hãng hàng không đã thống nhất các yếu tố cơ bản của 777: mặt cắt ngang có kích thước gần với 747, sức chứa 325 hành khách, nội thất linh hoạt, 1 buồng theo mô hình glass cockpit với hệ thống hiển thị LCD, hệ thống điều khiển fly-by-wire và có hiệu quả chi phí hành khách-hành trình hơn 10% so với A320 và MD-11. Đồng thời, Boeing chọn nhà máy Everett tại Washington làm nơi sản xuất chính và cũng là nơi lắp ráp cuối cùng của 777.

800px-Engine_of_Jet_Airways_Boeing_777-300ER.
Động cơ GE90 được trang bị trên Boeing 777-300ER​

Ngày 14 tháng 10 năm 1990, United Airlines trở thành khách hàng đầu tiên của 777 với đơn đặt hàng 34 chiếc tổng trị giá 11 tỷ đô la trang bị động cơ Pratt & Whitney và một số tùy chọn khác. Hãng hàng không United đã sử dụng 777 để mở 3 tuyến đường bay khác nhau bao gồm: Chicago tới Hawaii, Chicago tới Châu Âu và chuyến bay không chặn dừng từ Denver tới Hawaii.

Tháng 1 năm 1993, một nhóm các nhà phát triển từ hãng hàng không United đã tham gia vào nhóm thiết kế Boeing tại nhà máy Everett. 240 đội thiết kế, mỗi nhóm 40 thành viên đã giải quyết gần 1500 vấn đề độc lập trong giai đoạn thiết kế các thành phần trên Boeing 777.

Boeing 777 là máy bay thương mại đầu tiên trên thế giới được thiết kế hoàn toàn bằng máy tính. Mỗi bản vẽ thiết kế đều được dựng mô hình 3D trên máy bằng hệ thống phần mềm CAD mang tên CATIA được phát triển bởi IBM và Dassault Systemes. Phần mềm cho phép các kỹ sư có thể lắp ráp các bộ phận máy bay ảo, mô phỏng và kiểm tra sự ăn khớp của hàng nghìn các linh kiện cấu thành nhằm giảm được chi phí sản xuất các mô hình thử nghiệm tốn kém.

Sản xuất và thử nghiệm

Quá trình sản xuất có sự tham gia của nhiều nhà sản xuất từ nhiều nơi trên thế giới bao gồm: Mitsubishi Heavy Industries và Kawasaki Heavy Industries (chịu trách nhiệm lớp vỏ phần thân), Fuji Heavy Industries sản xuất phần cánh trung tâm, Hawker de Havilland (cánh nâng đuôi) và bánh lái được sản xuất bởi công ty công nghệ hàng không vũ trụ Úc. Ngoài ra, Boeing đã ký thỏa thuận bảo đảm 20% rủi ro với đại diện các nhà sản xuất tại Nhật Bản.

Ban đầu, động cơ trên 777-200 được lựa chọn giữa 3 nhà sản xuất General Electric (GE), Pratt & Whitney và Rolls-Royce. Mỗi nhà sản xuất đều đồng ý phát triển môt động cơ 340 kN và có lực đẩy phản lực đủ lớn để trang bị cho máy bay phản lực 2 động cơ lớn nhất thế giới này.

Boeing đã đầu tư thêm khoảng chi phí 1,5 tỷ đô la để mở rộng quy mô của nhà máy Everett với 2 dây chuyền lắp ráp mới. Đồng thời, các phương pháp lắp ráp mới cũng được Boeing phát triển với 1 cánh tay robot điều khiển bằng máy tính có thể xoay 180 độ cho phép công nhân có thể thao tác ở phần phía trên thân máy bay.

800px-Air_India_Boeing_777-200LR_Roll_Out_Everett,_WA.
1 chiếc Boeing 777 sản xuất cho Hãng hàng không Ấn Độ ra khỏi nhà máy Everett​

Những bộ phận cơ bản đầu tiên của 777 đã được bắt đầu lắp ráp vào ngày 4 tháng 1 năm 1993. Tới thời điểm bấy giờ, hãng đã có tổng cộng 118 đơn đặt hàng với 95 tùy chọn từ 10 hãng hàng không khác nhau. Toàn bộ dự án Boeing 777 đã tiêu tốn 4 tỷ đô la của Boeing và 2 tỷ đô la được bổ sung từ các nhà cung cấp thiết bị.

Vào ngày 9 tháng 4 năm 1994, chiếc máy bay đầu tiên mang số hiệu WA001 được chính thức giới thiệu trong buổi lễ ra mắt với sự chứng kiến của tổng cộng 100.000 khách mời. Chuyến bay đầu tiên diễn ra vào ngày 12 tháng 6 năm 1994 dưới sự chỉ huy của cơ trưởng John E Cashman. Sự kiện này đánh dấu bắt đầu chương trình thử nghiệm kéo dài 11 tháng, dài hơn bất kỳ chương trình thử nghiệm nào được Boeing thực hiện trên các dòng máy bay trước đó.

Có tổng cộng 9 chiếc máy bay đã được thực hiện các chuyến bay thử nghiệm tại những địa điểm từ căn cứ không quân Edwards thuộc sa mạc ở California cho đến khu vực thuộc Alaska. Boeing cũng thực hiện bài kiểm tra bay trong vòng 180 phút với 1 động cơ phản lực nhằm đáp ứng yêu cầu của ETOPS.

Đi vào hoạt động

800px-United_Airlines_777_N777UA.
Chiếc Boeing 777-200 đầu tiên được khai thác thương mại​

Ngày 15 tháng 5 năm 1995, Boeing đã bàn giao chiếc 777 đầu tiên cho hãng hàng không United Airlines. Đến ngày 30 tháng 5, Cơ quan hàng không liên bang Mỹ (FAA) đã cấp chứng chỉ ETOPS-180 (được phép bay tuyến đường có thời gian dưới 180 phút) cho chiếc Boeing 777 với động cơ Pratt & Whitney PW4084 nhờ vào khả năng thực hiện chuyến bay. Đây là chiếc máy bay dân dụng thương mại đầu tiên được cấp chứng nhận ETOPS-180 kể từ khi bộ tiêu chuẩn này được ban hành.

Không lâu sau đó, thời gian cho phép bay trên Boeing đã được mở rộng lên ETOPS-207 phút vào tháng 11 cùng năm. Ngày 7 tháng 6 năm 1995, chuyến bay thương mại đầu tiên đã xuất phát từ sân bay London Heathrow đến sân bay quốc tế Dulles gần Washington.

800px-United_Airlines_B777-200_N780UA.

Đến ngày 12 tháng 11 năm 1995, Boeing chuyển giao mẫu 777 trang bị động cơ GE90-77B cho hãng hàng không British Airways và được đưa vào khai thác 5 ngày sau đó. Do gặp vấn đề về hộp số, đội bay Boeing 777 đã tạm ngừng khai thác tuyến đường bay xuyên Đại Tây Dương vào năm 1997. 1 năm sau đó, hãng hàng không British đưa tuyến đường bay trở lại hoạt động bình thường sau khi GE đưa ra 1 bản nâng cấp cho động cơ.

Chiếc 777 sử dụng động cơ Rolls-Royce 877 đầu tiên được chuyển đến cho hãng hàng không quốc tế Thái Lan vào ngày 31 tháng 3 năm 1996. Dù sử dụng động cơ của hãng nào, mỗi chiếc Boeing 777 khi đưa vào khai thác thương mại đều được đảm bảo chứng nhận ETOPS-180. Tính đến năm 1998, Boeing 777 từ các hãng hàng không đã có tổng số giờ bay lên tới 900.000 giờ. Boeing tuyên bố đội bay 777 có độ tin cậy điều vận lên tới trên 99%.

Do chi phí nhiên liệu ngày 1 tăng cao, các hãng hàng không bắt đầu chú ý đến Boeing 777 như một giải pháp thay thế cho các máy bay phản lực thân rộng khác. Với động cơ hiện đại có tỷ lệ hư hỏng cực kỳ thấp theo tiêu chuẩn của ETOPS và hiệu quả hoạt động cao, Boeing 777 hoản toàn có thể thay thế các máy bay phản lực 4 động cơ khác như Airbus A380 hoặc Boeing 747.

Các biến thể tiếp theo

800px-Emirates_Boeing_777_fleet_at_Dubai_International_Airport_Wedelstaedt_.
Đội bay Boeing 777 tại hãng hàng không Dubai​

Sau nguyên bản ban đầu, Boeing đã phát triển các phiên bản tiếp theo với trọng lượng lớn hơn cho phép nâng cao tầm bay và tải trọng. Phiên bản đầu tiên được đặt tên là 777-200IGW, sau đó đổi thành 777-200ER và thực hiện chuyến bay đầu tiên vào ngày 7 tháng 10 năm 1996. Ngay sao đó, 777-200ER đã nhận được chứng chỉ của FAA và JAA vào tháng 1 năm 1997 và được đưa vào khai thác thương mại bởi hãng hàng không British Airways vào ngày 9 tháng 2.

Ngày 2 tháng 4 năm 1997, hãng hàng không Malaysia đã đặt tên cho 777-200ER là “Super Ranger” sau khi lần đầu tiên phá kỷ lục bay không điểm dừng dài nhất. Đoạn đường từ Boeing Field, bang Seattle đến Kuala Lumpur với đường bay dài 20.044 km được Boeing 777-200ER hoàn tất trong vòng 21 giờ 23 phút.

800px-Elal.b777-200.4x-ecd.arp.

Sau sự ra đời và những thành công của 777-200ER, Boeing bắt đầu chú ý tới việc phát triển phiên bản tiếp theo là 777-300 với chiều dài thân là 73,9 m, dài hơn phiên bản ban đầu 20%. Đây là chiếc máy bay dài nhất từng được sản xuất (cho đến khi A340-600 ra đời). Ngày 16 tháng 10 năm 1997, Boeing 777-300 thực hiện chuyến bay đầu tiên và được FAA, JAA cấp chứng chỉ vào ngày 4 tháng 5 năm 1998 và bắt đầu đưa vào khai thác thương mại vào ngày 21 tháng 5 bởi hãng hàng không Cathay Pacific.

Kể từ khi bắt đầu phát triển, Boeing đã xác định hướng phát triển chủ đạo là sản xuất những chiếc 777 có tầm bay siêu dài. Dự án đầu tiên là 777-100X với chiều dài thân ngắn hơn phiên bản gốc nhằm giảm tải trọng và tăng tầm bay. Tuy nhiên, do có số lượng ghế hành khách ít hơn so với 777-200 nên sẽ làm cho chi phí trên mỗi ghế hành khách lớn hơn.

Đến cuối những năm 1990, dự án trên được chuyển thành phiên bản có tầm bay dài hơn với động cơ mạnh hơn và có sức đẩy lớn hơn (440 kN). GE đã cho ra đời mẫu động cơ GE90-115B trong khi đó Roll-Royce cho ra mắt Trent 8104. Cuối cùng, Boeing đã chính thức hợp tác với General Electric và sử dụng động cơ GE90 cho tất cả các phiên bản mới của Boeing 777.

Thiết kế và công nghệ

Boeing đã trang bị hàng loạt các công nghệ hiện đại trên 777 bao gồm hệ thống điều khiển điện tử fly-by-wire, sử dụng hệ thống phần mềm theo dõi kỹ thuật hàng không chuyên dụng, buồng lái glass cockpit với màn hình điều khiển trung tâm LCD, đặc biệt là lần đầu tiên trang bị hệ thống mạng điều khiển kỹ thuật hàng không bằng cáp quang cho máy bay dân dụng.

Hệ thống điều khiển bay kỹ thuật số fly-by-wire

Trong thiết kế của hệ thông fly-by-wire đầu tiên được trang bị trên máy bay của mình, Boeing đã quyết định giữ lại cần điều khiển chữ U trên các dòng máy bay trước đó thay vì sử dụng slidestick như máy bay của Airbus hay một số máy bay tiêm kích khác.

Chính nhờ thiết kế trên đã giúp buồng lái của 777 trở nên gọn gàng với các thao tác điều khiển đơn giản hơn so với các mẫu trước đó. Hệ thống fly-by-wire trên 777 còn được kết hợp với hệ thống flight envelope protection – hệ thống kết hợp lệnh điều khiển của phi công với phân tích thông số bay hiện hành đã qua xử lý của máy tính nhằm chống tình trạng máy bay chòng chành hoặc mất thăng bằng bởi điều kiện thời tiết. Tuy nhiên, hệ thống kết hợp này vẫn có thể được chuyển sang điều khiển hoàn toàn bằng tay khi phi công có nhu cầu.

Khung máy bay và các hệ thống cơ khí

800px-Aa.b777-200er.n788an.mains.arp.
Động cơ, hệ thống hạ cánh trên Boeing 777​

Cánh của 777 có thiết kế siêu tối ưu, nghiêng về phía sau 31,6 độ và được tối ưu hóa cho tốc độ bay 0,83 Mach. Bên cạnh đó, cánh cũng được thiết kế dày hơn và sải cánh dài hơn so với các máy bay dân dụng trước đó nhằm nâng cao tải trọng và tầm bay xa hơn, cải thiện hiệu năng cất cánh và khả năng bay ổn định ở độ cao cao hơn.

Cánh của 777 cũng bao gồm các thùng nhiên liệu 181.300 lít. Điều này cho phép 777 (777-200LR) có khả năng thực hiện những chuyến bay siêu dài như từ Toronto tới Hongkong mà không cần dừng. Vào năm 2013, phiên bản nâng cấp là 777X được giới thiệu với cánh được làm bằng vật liệu composite với sải cánh và thiết kế tương tự như trên cánh của máy bay 787.

Một số thành phần của khung sườn trên 777 cũng được chế tạo từ vật liệu composite như sàn cabin hay bánh lái đuôi rudder khiến trọng lượng của 777 nhẹ hơn tới 9% so với nguyên bản ban đầu của nó. Mặt cắt ngang thân của 777 có hình tròn và đuôi phía sau được vuốt nhọn.

800px-Boeing-777-300_chassis.
Hệ thống hạ cánh với 6 bánh mỗi bên đặc trưng cho Boeing 777​

Boeing 777 cũng sở hữu hệ thống càng hạ cánh lớn nhất so với các máy bay phản lực dân dụng khác với bộ 6 bánh xe đặt trưng. Thiết kế này giúp giảm được trọng lượng và góp phần đơn giản hóa hệ thống phanh và thủy lực trên máy bay.

Trên phiên bản 300ER, mỗi chiếc lốp trong bộ 6 bánh xe có thể chịu được cân nặng 26.980 Kg, nặng hơn bất kỳ máy bay thân rộng nào khác như 747-400.

Nội thất

800px-Etihad_Airways_Boeing_777-3FXER_Coral_Wedelstaedt.

Boeing 777 có thiết kế nội thất độc quyền của Boeing được ghép từ các tấm cong, trần máy bay rộng và hệ thống chiếu sáng gián tiếp. Các cấp độ ghế hành khách đa dạng từ ghế hạng nhất cho tới khoang hành khách phổ thông. Cho tới khi 787 ra đời, đây chính là máy bay thương mại có kích thước cửa sổ lớn nhất (380 x 250 mm).

Cabin máy bay còn được trang bị “khu vực linh hoạt” cho phép dễ dàng thay đổi công năng sử dụng theo từng mục đích trong thời gian nhanh chóng. Trên một số chiếc 777 còn được trang bị khu vực nội thất VIP dành riêng cho những đối tượng hành khách đặc biệt.

[.NETWorld] Database Initialization Strategies in Code-First:

You already created database after running you code first application first time, but what about second time onwards?? Will it create new database every time you run the application? What about production environment? How to alter database when you change your domain model? To handle these scenarios, you have to use one of the database initialization strategies.

 

There are four different database Initialization strategies:

 

  1. CreateDatabaseIfNotExists: This is default initializer. As name suggests, it will create the database if not exists as per the configuration. However, if you change the model class and then run the application with this initializer then it will throw an exception. 
  2. DropCreateDatabaseIfModelChanges: This initializer drops existing database and creates new database if your model classes (entity classes) have been changed. So you don’t have to worry about maintaining your database schema when your model classes changes. 
  3. DropCreateDatabaseAlways: As name suggests, this initializer drops an existing database every time you run the application irrespective of whether your model classes have changed or not. This will be useful when you want fresh database every time you run the application while developing. 
  4. Custom DB Initializer: You can also create your own custom initializer if any of the above doesn’t satisfy your requirement or you want to do some other process when it initialize the database using above initializer. 

 

To use one of the above DB initialization strategies, you have to set the DB Initializer using Database class in Context class as following:

     
    public class SchoolDBContext: DbContext 
    {

        public SchoolDBContext(): base("SchoolDBConnectionString") 
        {
            Database.SetInitializer<SchoolDBContext>(new CreateDatabaseIfNotExists<SchoolDBContext>());

            //Database.SetInitializer<SchoolDBContext>(new DropCreateDatabaseIfModelChanges<SchoolDBContext>());
            //Database.SetInitializer<SchoolDBContext>(new DropCreateDatabaseAlways<SchoolDBContext>());
            //Database.SetInitializer<SchoolDBContext>(new SchoolDBInitializer());
        }
        public DbSet<Student> Students { get; set; }
        public DbSet<Standard> Standards { get; set; }
    }

You can also create your custom DB initializer by inheriting one of the intializer as below:

    
    public class SchoolDBInitializer :  DropCreateDatabaseAlways<SchoolDBContext>
    {
        protected override void Seed(SchoolDBContext context)
        {
            base.Seed(context);
        }
    }

As you can see in the above code, we have created new class SchoolDBInitializer which is derived from DropCreateDatabaseAlways initializer.

 

Set db initializer in the configuration file:

 

You can also set db initializer in the configuration file. For example, to set default initializer in app.config:

   
    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <appSettings>
        <add key="DatabaseInitializerForType SchoolDataLayer.SchoolDBContext, SchoolDataLayer"         
            value="System.Data.Entity.DropCreateDatabaseAlways`1[[SchoolDataLayer.SchoolDBContext, SchoolDataLayer]], EntityFramework" />
      </appSettings>
    </configuration>

You can set custom db initializer as following:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <appSettings>    
        <add key="DatabaseInitializerForType SchoolDataLayer.SchoolDBContext, SchoolDataLayer"
             value="SchoolDataLayer.SchoolDBInitializer, SchoolDataLayer" />
      </appSettings>
    </configuration>

So this way you can use DB initialization strategy for your application.

[.NETWorld] Code First: Inside DbContext Initialization

A lot of stuff happens when you use a DbContext instance for the first time. Most of the time you don’t worry about this stuff, but sometimes it’s useful to know what’s happening under the hood. And even if it’s not useful, it’s hopefully interesting for its geek value alone.

 

Note that even though there is a lot of detail below I’ve actually simplified things quite a lot to avoid getting totally bogged down in code-like details. Also, I’m writing this from memory without looking at the code so forgive me if I forget something. 🙂

Creating a DbContext instance

Not very much happens when the context instance is created. The initialization is mostly lazy so that if you never use the instance, then you pay very little cost for creating the instance.

It’s worth noting that SaveChanges on an un-initialized context will also not cause the context to be initialized. This allows patterns that use auto-saving to be implemented very cheaply when the context has not been used and there is therefore nothing to save.

One thing that does happen at this stage is that the context is examined for DbSet properties and these are initialized to DbSet instances if they have public setters. This stops you getting null ref exceptions when you use the sets but still allows the sets to be defined as simple automatic properties. The delegates used to do this are cached in a mechanism similar to the one described here.

DbContext initialization

The context is initialized when the context instance is used for the first time. “Use” means any operation on the context that requires database access or use of the underlying Entity Data Model (EDM). The initialization steps are:

  1. The context tries to find a connection or connection string:
    1. If a DbConnection was passed to the constructor, then this is used.
    2. Else, if a full connection string was passed, then this is used.
    3. Else, if the name of a connection string was passed and a matching connection string is found in the config file, then this is used.
    4. Else, the database name is determined from the name passed to the constructor or from the context class name and the registered IConnectionFactory instance is used to create a connection by convention.
  2. The connection string is examined to see if it is an Entity Framework connection string containing details of an EDM to use or if it is a raw database connection string containing no model details.
    1. If it is an EF connection string, then an underlying ObjectContext is created in Model First/Database First mode using the EDM (the CSDL, MSL, and SSDL from the EDMX) in the connection string.
    2. If it a database connection string, then the context enters Code First mode and attempts to build the Code First model as described in the next section.

I made a post on the EF Team blog that describes some of the connection handling in more detail.

Building the Code First model

The EDM used by Code First for a particular context type is cached in the app-domain as an instance of DbCompiledModel. This caching ensures that the full Code First pipeline for building a model only happens once when the context is used for the first time. Therefore, when in Code First mode:

  1. DbContext checks to see if an instance of DbCompiledModel has been cached for the context type. If the model is not found in the cache, then:
    1. DbContext creates a DbModelBuilder instance.
      1. By default, the model builder convention set used is Latest. A specific convention set can be used by setting the DbModelBuilderVersionAttribute on your context.
    2. The model builder is configured with each entity type for which a DbSet property was discovered.
      1. The property names are used as the entity set names, which is useful when you’re creating something like an OData feed over the model
    3. The IncludeMetadataConvention convention is applied to the builder. This will include the EdmMetadata entity in the model unless the convention is later removed.
    4. The ModelContainerConvention and ModelNamespaceConvention are applied to the builder. These will use the context name as the EDM container name and the context namespace as the EDM namespace. Again, this is useful for services (like OData) that are based on the underlying EDM.
    5. OnModelCreating is called to allow additional configuration of the model.
    6. Build is called on the model builder.
      1. The model builder builds an internal EDM model representation based on configured types and reachability from those types and runs all the Code First conventions which further modify the model/configuration.
        1. The connection is used in this process since the SSDL part of the model depends on the target database, as represented by the provider manifest token.
    7. Compile is called on the DbModel to create a DbCompiledModel. DbCompiledModel is currently a wrapper around the MetadataWorkspace.
      1. The model hash is also created by the call to compile.
    8. The DbCompiledModel is cached.
  2. The DbCompiledModel is used to create the underlying ObjectContext instance.

Database initialization

At this point we have an underlying ObjectContext, created either through Code First or using the EDM in the connection string.

DbContext now checks whether or not database initialization has already happened in the app-domain for the type of the derived DbContext in use and for the database connection specified. If initialization has not yet happened, then:

  1. DbContext checks whether or not an IDatabaseInitializer instance has been registeredfor the context type.
    1. If no initializer (including null) has been explicitly registered then a default initializer will be automatically registered.
      1. In Code First mode, the default initializer is CreateDatabaseIfNotExists.
      2. In Database/Model First mode, the default initializer is null, meaning that no database initialization will happen by default. (Because your database almost always already exists in Database/Model First mode.)
  2. If a non-null initializer has been found, then:
    1. A temporary ObjectContext instance is created that is backed by the same EDM as the real ObjectContext. This temp is used by the DbContext instance for all work done by the initializer and then thrown away. This ensures that work done in the initializer does not leak into the context later used by the application.
    2. The initializer is run. Using the Code First default CreateDatabaseIfNotExists as an example, this does the following:
      1. A check is made to see whether or not the database already exists.
      2. If the database does not exist, then it is created:
        1. This happens through the CreateDatabase functionality of the EF provider. Essentially, the SSDL of the model is the specification used to create DDL for the database schema which is then executed.
          1. If the EdmMetadata entity was included in the model, then the table for this is automatically created at the same time since it is part of the SSDL just like any other entity.
        2. If the EdmMetadata entity was included in the model, then the model hashgenerated by Code First is written to the database by saving an instance of EdmMetadata.
        3. The Seed method of the initializer is called.
        4. SaveChanges is called to save changes made in the Seed method.
      3. If the database does exist, then a check is made to see if the EdmMetadata entity was included in the model and, if so, whether there is also a table with a model hash in the database.
        1. If EdmMetadata is not mapped or the database doesn’t contain the table, then it is assumed that the database matches the model. This is what happens when you map to an existing database, and in this case it is up to you to ensure that the model matches the database. (Note DropCreateDatabaseIfModelChanges would throw in this situation.)
        2. Otherwise, the model hash in the database is compared to the one generated by Code First. If they don’t match, then an exception is thrown. (DropCreateDatabaseIfModelChanges would drop, recreate, and re-seed the database in this situation.)
    3. The temporary ObjectContext is disposed.
  3. Control returns to whatever operation it was that caused initialization to run.

That’s the basics. Like I mentioned above, I missed some details intentionally, and I probably missed some more by mistake. Hopefully it was somewhat useful/interesting anyway.

Thanks for reading!
Arthur

P.S. There is an alternate theory of how DbContext works that suggests nuget introduces a herd of unicorns into your machine which then run on treadmills to create magic entity juice that in turn magically connects your objects to your database. I cannot comment on this theory without breaking confidentiality agreements I have signed with the unicorn king. Or something.

[.NETWorld] EF 6.1: Creating indexes with IndexAttribute

Since EF 4.3 it has been possible to use CreateIndex and DropIndex in Code First Migrations to create and drop indexes. However this had to be done manually by editing the migration because the index was not included anywhere in the Code First model. Now with EF 6.1 it is possible to add index specifications to the model such that creating and dropping indexes can be handled automatically by Migrations.

Single column indexes

Consider a simple Blog entity:

1
2
3
4
5
6
7
public class Blog
{
    public int Id { get; set; }
    public string Title { get; set; }
    public int Rating { get; set; }
    public virtual ICollection<Post> Posts { get; set; }
}

Let’s assume this entity is already in our model and migrations have been created and applied so the model and database are both up-to-date. The easiest way to add an index is to place IndexAttribute onto a property. For example, let’s add an index to the column mapped to by the Rating property:

1
2
3
4
5
6
7
8
9
10
public class Blog
{
    public int Id { get; set; }
    public string Title { get; set; }
    [Index]
    public int Rating { get; set; }
    public virtual ICollection<Post> Posts { get; set; }
}

After doing this using Add-Migration will scaffold a migration something like this:

1
2
3
4
5
6
7
8
9
10
11
12
public partial class Two : DbMigration
{
    public override void Up()
    {
        CreateIndex("dbo.Blogs", "Rating");
    }
    public override void Down()
    {
        DropIndex("dbo.Blogs", new[] { "Rating" });
    }
}

The index is being created with a default name and default options. The defaults are as follows:

  • Name: IX_[column_name]
  • Not unique
  • Not clustered

You can also use IndexAttribute to give the index a specific name and options. For example, let’s add a name to the index for the Rating column:

1
2
3
4
5
6
7
8
9
10
public class Blog
{
    public int Id { get; set; }
    public string Title { get; set; }
    [Index("RatingIndex")]
    public int Rating { get; set; }
    public virtual ICollection<Post> Posts { get; set; }
}

Scaffolding another migration for this change results in:

1
2
3
4
5
6
7
8
9
10
11
12
public partial class Three : DbMigration
{
    public override void Up()
    {
        RenameIndex(table: "dbo.Blogs", name: "IX_Rating", newName: "RatingIndex");
    }
    public override void Down()
    {
        RenameIndex(table: "dbo.Blogs", name: "RatingIndex", newName: "IX_Rating");
    }
}

Notice that Migrations has scaffolded a rename for the index from the default name to the new name.

Multiple column indexes

Indexes that span multiple columns can also be scaffolded by using the same index name on multiple properties. For example:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Blog
{
    [Index("IdAndRating", 1)]
    public int Id { get; set; }
    public string Title { get; set; }
    [Index("RatingIndex")]
    [Index("IdAndRating", 2, IsUnique = true)]
    public int Rating { get; set; }
    public virtual ICollection<Post> Posts { get; set; }
}

Notice that the order of columns in the index is also specified. The unique and clustered options can be specified in one or all IndexAttributes. If these options are specified on more than one attribute with a given name then they must match.

Scaffolding a migration for this change results in:

1
2
3
4
5
6
7
8
9
10
11
12
public partial class Four : DbMigration
{
    public override void Up()
    {
        CreateIndex("dbo.Blogs", new[] { "Id", "Rating" }, unique: true, name: "IdAndRating");
    }
    public override void Down()
    {
        DropIndex("dbo.Blogs", "IdAndRating");
    }
}

Index conventions

The ForeignKeyIndexConvention Code First convention causes indexes to be created for the columns of any foreign key in the model unless these columns already have an index specified using IndexAttribute. If you don’t want indexes for your FKs you can remove this convention:

1
2
3
4
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Conventions.Remove<ForeignKeyIndexConvention>();
}

What IndexAttribute doesn’t do

IndexAttribute can be used to create a unique index in the database. However, this does not mean that EF will be able to reason about the uniqueness of the column when dealing with relationships, etc. This feature usually referred to as support for “unique constraints” which can be voted for as a feature suggestion and on the CodePlex work item.

[Technology] Công nghệ mới giúp khai thác năng lượng từ sóng dưới đáy biển

Rất nhiều tổ chức trên thế giới đang tìm kiếm những phương pháp khai thác năng lượng của sóng biển làm năng lượng tái tạo . Tuy nhiên, chưa tổ chức nào lại áp dụng phương pháp khai thác từ đáy biển như đại học California tại Berkeley ( UC Berkeley ). Mới đây, họ đã phát triển một hệ thống có tên gọi ” thảm đáy biển ” lấy ý tưởng từ lớp bùn đáy biển nhằm khai thác tiềm năng năng lượng từ những con sóng.

Công nghệ mới giúp khai thác năng lượng từ sóng dưới đáy biển

Bùn đáy biển được biết đến với khả năng hấp thu chấn động của những con sóng dưới đại dương. Khi một cơn bão mạnh tấn công vịnh Mexico, các ngư dân tại đây biết rằng đáy đại dương phủ đầy bùn sẽ đóng vai trò như một bề mặt phụ, mềm hơn giúp giảm tác động của sóng và cầm chân cơn bão.

Lấy ý tưởng từ hiện tượng này, nhóm nghiên cứu đến từ UC Berkeley đã nghĩ ra một hệ thống trong đó năng lượng của sóng không chỉ được hấp thu mà còn được chuyển đổi thành năng lượng hữu ích.

Hệ thống bao gồm một tấm thảm cao su lớn được đặt bên trên các bộ truyền động thủy lực, xy-lanh và máy bơm để tiếp nhận chuyển động của các cơn sóng tới. Khi di chuyển lên xuống, tấm thảm tạo ra áp lực nước trong các xy-lanh và áp lực này được dẫn ngược vào bờ để chuyển đổi thành năng lượng hữu ích.

Các thử nghiệm được thực hiện tại UC Berkeley cho thấy tấm thảm có khả năng hấp thu hơn 90% năng lượng sóng . Theo các nhà nghiên cứu, một tấm thảm có diện tích 1 m2 có thể tạo ra đủ năng lượng điện cho 2 ngôi nhà tiêu chuẩn tại Mỹ. Trong khi đó, một tấm thảm 100 m2 sẽ có thể cung cấp năng lượng tương đương một sân bóng đá được bao phủ bởi các tấm pin mặt trời với diện tích 6400 m2.

Công nghệ mới giúp khai thác năng lượng từ sóng dưới đáy biển

Reza Alam – phó giáo sư đến từ khoa kỹ thuật cơ học tại UC Berkeley cho biết: “Chúng tôi đã lên kế hoạch thử nghiệm hệ thống này tại biển trong vòng 2 năm tới và hy vọng rằng 10 năm sau hệ thống sẽ sẵn sàng để thương mại hóa.”

Nhóm nghiên cứu cũng nhấn mạnh về độ bền và độ linh hoạt của hệ thống. Được phát triển dựa trên ý tưởng đáy biển, được chế tạo từ các vật liệu dẻo không ăn mòn và nhằm mục đích lắp đặt tại các vùng nước nông ven biển ở độ sâu 18 m, hệ thống có thể chịu được động lượng lớn của các vùng biển động. Nhóm cho biết hệ thống có thể được vận chuyển dễ dàng và thiết kế tháo lắp dạng mô-đun cho phép điều chỉnh tỉ lệ chiều rộng tùy theo môi trường và nhu cầu năng lượng.

Công nghệ mới giúp khai thác năng lượng từ sóng dưới đáy biển

Bên cạnh việc mang lại một nguồn năng lượng thay thế , quá trình chuyển đổi còn tạo ra nước biển ở áp suất cao có thể được dùng để khử muối và cung cấp nguồn nước sạch cho người dân tại khu vực duyên hải.

Sau khi thử nghiệm thành công tại phòng thí nghiệm tại Berkeley, nhóm nghiên cứu đã đưa dự án lên trang Experiment để gây quỹ từ cộng đồng nhằm đưa dự án tiến đến giao đoạn tiếp theo. Nếu đạt được mục tiêu, nhóm nghiên cứu sẽ phát triển một nguyên mẫu lớn hơn để kiểm tra hiệu năng và thử nghiệm vật liệu phù hợp dành cho các ứng dụng thực tế ngoài đại dương.

[.NETWorld] YouTube Downloader Using C# .NET

Attached new version Smile | :) .

Introduction

This article shows how to download YouTube videos using C# code only. The code is very simple to understand and anyone can easily integrate it to in their solution or project.

I didn’t use any third party library to do this task. All you need is to take two .cs files and integrate them to your project.

Using the code

There are two main classes in this project:

YouTubeVideoQuality Class

This is the entity that describes the video.

 Collapse | Copy Code
public class YouTubeVideoQuality 
{
    /// <summary>
    /// Gets or Sets the file name
    /// </summary>
    public string VideoTitle { get; set; }
    /// <summary>
    /// Gets or Sets the file extention
    /// </summary>
    public string Extention { get; set; }
    /// <summary>
    /// Gets or Sets the file url
    /// </summary>
    public string DownloadUrl { get; set; }
    /// <summary>
    /// Gets or Sets the youtube video url
    /// </summary>
    public string VideoUrl { get; set; }
    /// <summary>
    /// Gets or Sets the file size
    /// </summary>
    public Size Dimension { get; set; }

    public override string ToString()
    {
        return Extention + " File " + Dimension.Width + 
                           "x" + Dimension.Height;
    }

    public void SetQuality(string Extention, Size Dimension)
    {
        this.Extention = Extention;
        this.Dimension = Dimension;
    }
}

YouTubeDownloader Class

This class downloads YouTube videos:

 Collapse | Copy Code
public class YouTubeDownloader
{
    public static List<YouTubeVideoQuality> GetYouTubeVideoUrls(params string[] VideoUrls)
    {
        List<YouTubeVideoQuality> urls = new List<YouTubeVideoQuality>();
        foreach (var VideoUrl in VideoUrls)
        {
            string html = Helper.DownloadWebPage(VideoUrl);
            string title = GetTitle(html);
            foreach (var videoLink in ExtractUrls(html))
            {
                YouTubeVideoQuality q = new YouTubeVideoQuality();
                q.VideoUrl = VideoUrl;
                q.VideoTitle = title;
                q.DownloadUrl = videoLink + "&title=" + title;
                if (getQuality(q))
                    urls.Add(q);
            }
        }
        return urls;
    }

    private static string GetTitle(string RssDoc)
    {
        string str14 = Helper.GetTxtBtwn(RssDoc, "'VIDEO_TITLE': '", "'", 0);
        if (str14 == "") str14 = Helper.GetTxtBtwn(RssDoc, "\"title\" content=\"", "\"", 0);
        if (str14 == "") str14 = Helper.GetTxtBtwn(RssDoc, "&title=", "&", 0);
        str14 = str14.Replace(@"\", "").Replace("'", "'").Replace(
                "\"", "&quot;").Replace("<", "&lt;").Replace(
                ">", "&gt;").Replace("+", " ");
        return str14;
    }

    private static List<string> ExtractUrls(string html)
    {
        html = Uri.UnescapeDataString(Regex.Match(html, "url_encoded_fmt_stream_map=(.+?)&", 
                                      RegexOptions.Singleline).Groups[1].ToString());
        MatchCollection matchs = Regex.Matches(html, 
          "url=(.+?)&quality=(.+?)&fallback_host=(.+?)&type=(.+?)&itag=(.+?),", 
          RegexOptions.Singleline);
        bool firstTry = matchs.Count > 0;
        if (!firstTry)
            matchs = Regex.Matches(html, 
                     "itag=(.+?)&url=(.+?)&type=(.+?)&fallback_host=(.+?)&sig=(.+?)&quality=(.+?),{0,1}", 
                     RegexOptions.Singleline);
        List<string> urls = new List<string>();
        foreach (Match match in matchs)
        {
            if (firstTry)
                urls.Add(Uri.UnescapeDataString(match.Groups[1] + ""));
            else urls.Add(Uri.UnescapeDataString(match.Groups[2] + "") + "&signature=" + match.Groups[5]);
        }
        return urls;
    }

    private static bool getQuality(YouTubeVideoQuality q)
    {
        if (q.DownloadUrl.Contains("itag=5"))
            q.SetQuality("flv", new Size(320, 240));
        else if (q.DownloadUrl.Contains("itag=34"))
            q.SetQuality("flv", new Size(400, 226));
        else if (q.DownloadUrl.Contains("itag=6"))
            q.SetQuality("flv", new Size(480, 360));
        else if (q.DownloadUrl.Contains("itag=35"))
            q.SetQuality("flv", new Size(640, 380));
        else if (q.DownloadUrl.Contains("itag=18"))
            q.SetQuality("mp4", new Size(480, 360));
        else if (q.DownloadUrl.Contains("itag=22"))
            q.SetQuality("mp4", new Size(1280, 720));
        else if (q.DownloadUrl.Contains("itag=37"))
            q.SetQuality("mp4", new Size(1920, 1280));
        else if (q.DownloadUrl.Contains("itag=38"))
            q.SetQuality("mp4", new Size(4096, 72304));
        else return false;
        return true;
    }
}

Points of Interest

Using this code you can select the video quality depending in your internet connection speed to start download.

Many people have slow internet connections and they can not watch videos from YouTube, so I made this code to help those people to download YouTube videos to their PC’s so they can watch the videos offline.

Updates

Thanks to Motaz Alnuweiri, the Downloader works again. Added self download videos.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

[.NETWorld] Build End-to-End Apps with TypeScript

Over the past few years, I’ve been working a lot with the JavaScript language and building large-scale web applications. Although I have “Stockholm Syndrome” (JavaScript is one of my favorite programming languages), other developers don’t share my affection for the language. Developers don’t like JavaScript for many reasons. One of the main reasons is that JavaScript is difficult to maintain in a large-scale code base. In addition, JavaScript lacks certain language features, such as modules, classes, and interfaces.

Developers can use two main approaches to avoid JavaScript pitfalls. The first approach is to use plain JavaScript with JavaScript design patterns to mimic the behavior of modules, classes, and other missing JavaScript language features. I use this approach most of the time, but it can be very difficult for junior JavaScript developers because you need know JavaScript quite well to avoid its pitfalls.

Related: Is TypeScript Ready for Prime Time?

The second approach is to use JavaScript preprocessors. JavaScript preprocessors are design-time tools that use custom languages or known languages that later compile into JavaScript. Using this approach helps you create a more object-oriented–like code base and helps code maintainability. JavaScript preprocessors such as CoffeeScript, Dart, or GWT are very popular, but they force you to learn a new language or use languages such as Java or C# that are later compiled into JavaScript. What if you could use JavaScript instead, or a variation of JavaScript?

You’re probably asking yourself why you would use JavaScript or a JavaScript variant to compile into JavaScript. One reason is that ECMAScript 6, the latest JavaScript specifications, introduces a lot of the missing features in the JavaScript language. Also, because at the end of the process you get JavaScript code anyway, why not write the code in plain JavaScript from the start?

This is where TypeScript becomes very useful.

TypeScript to the Rescue

A year ago Microsoft released the first preview of a new language, TypeScript, written by a team led by Anders Hejlsberg, creator of the C# language. TypeScript is a JavaScript preprocessor that compiles into plain JavaScript. Unlike other JavaScript preprocessors, TypeScript was built as a typed superset of JavaScript, and it adds support for missing JavaScript features that aren’t included in the current version of ECMAScript. TypeScript aligns to the new JavaScript keywords that will be available when ECMAScript 6, the next version of JavaScript specifications, becomes the JavaScript standard. This means that you can use language constructs such as modules and classes in TypeScript now, and later on when ECMAScript 6 becomes the standard, your code will already be regular JavaScript code.

TypeScript is cross-platform and can run on any OS because it can run wherever JavaScript can run. You can use the language to generate server-side code written in JavaScript along with client-side code also written in JavaScript. This option can help you write an end-to-end application with only one language—TypeScript.

To install TypeScript, go to the TypeScript website. On the website you’ll find download links and an online playground that you can use to test the language. You can also view TypeScript demos in the website’s “run it” section. The website can be very helpful for new TypeScript developers.

I don’t go into great detail about TypeScript’s features in this article; for a more detailed explanation of the language, see Dan Wahlin’s “Build Enterprise-Scale JavaScript Applications with TypeScript.” I recommend that you read Wahlin’s article before you proceed any further with this article. You’ll need a good understanding of what TypeScript is before you jump into writing a simple end-to-end application using the language.

Creating the Server Side with Node.js

To demonstrate the ease of using TypeScript to write an application, let’s create a simple gallery of DevConnections conference photos. First, you need to create the server side. The application will use the node.js runtime to run the application back end.

Node.js is a platform to build web servers using the JavaScript language. It runs inside a Google V8 engine environment. V8 is the Chrome browser’s JavaScript engine. Node.js uses an event-driven model that helps create an efficient I/O-intensive back end. This article assumes that you know a little bit about node.js and Node Packaged Modules (npm). If you aren’t familiar with node.js, you should stop reading and go to the node.js website first.

Our application will also use the Express framework, which is a node.js web application framework. Express helps organize the web application server side into MVC architecture. Express lets you use view engines such as EJS and Jade to create the HTML that’s sent to the client. In addition, Express includes a routes module that you can use to create application routes and to access other features that help speed up the creation of a node.js server. For further details about Express, go to the Express website.

Creating the project. To create the application, you need to install node.js Tools for Visual Studio (NTVS). (As I write this article, NTVS is currently in first alpha and might be unstable.) NTVS includes project templates for node.js projects, IntelliSense for node.js code, debugging tools, and many other features that can help you with node.js development inside Visual Studio IDE.

After you install NTVS, create a blank Express application and call it DevConnectionsPhotos. Figure 1 shows the New Project dialog box, which includes all the installed NTVS project templates.

Figure 1: Creating a Blank Express Application

Figure 1: Creating a Blank Express Application

When NTVS asks you whether to run npm to install the missing dependencies for the project, you should select the option to run npm and allow it to retrieve all the Express packages.

Creating the views. In the Views folder, you should replace the layout.jade file with the code in Listing 1. This code is written in Jade view engine style, and it will render the HTML layout of the main application page.

Listing 1: Rendering the HTML Layout of the Main Application Page
doctype html
html
head
title=’DevConnections Photo Gallery’
link(rel=’stylesheet’, href=’/Content/app.css’)
link(rel=’stylesheet’, href=’/Content/themes/classic/galleria.classic.css’)
script(src=’/Scripts/lib/jquery-1.9.0.js’)
script(src=’/Scripts/lib/galleria-1.2.9.js’)
script(src=’/Content/themes/classic/galleria.classic.js’)
script(src=’/Scripts/app/datastructures.js’)
script(src=’/Scripts/app/dataservice.js’)
script(src=’/Scripts/app/bootstrapper.js’)
script(src=’/Scripts/app/app.js’)
body
block content

You should also replace the index.jade file, which includes the content block that will be injected into the layout.jade file during runtime. The new code for the index.jade file should look like that in Listing 2.

Listing 2: The index.jade File
extends layout
block content
div#container
header
img#DevConnectionsLogo(src=’/Content/Images/DevConnctionsLogo.png’, alt=’DevConnections Logo’)
h1=’DevConnections Photo Gallery’
section.main
div#galleria
img#light(src=”/Content/Images/Light.png”)

The index.jade file includes a declaration of a DIV element with a Galleria ID. You’ll use that DIV later on the client side to show the photo gallery that you’re implementing.

Implementing the server side. Before you use TypeScript, you should import the TypeScript runtime to the NTVS project. To do so, add the following line of code to the DevConnectionsPhotos.njsproj file:

<Import Project=”$(VSToolsPath)\TypeScript\Microsoft.TypeScript.targets” />

This line of code imports TypeScript to the project and allows you to use it to compile TypeScript files. (Note that the TypeScript Visual Studio runtime wasn’t a part of NTVS projects at the time I wrote this article.)

Now that the environment is ready and you’ve created the main web page, you should rename the app.js file, which exists in the root of the project, to app.ts by changing its postfix to .ts. Performing this action forces the code to run as TypeScript code rather than JavaScript code. Because TypeScript is a JavaScript superset, you can transform the app.js file, which is a simple Express template, to app.ts without any problems.

In the app.ts file, you should add a module dependency on the node.js file system module. This module exists under the name fs. To use this module, you should create a new variable called fs under the Module dependencies comment, as Listing 3 shows.

Listing 3: Creating the fs Variable
/**
* Module dependencies.
*/
var express = require(‘express’);
var routes = require(‘./routes’);
var user = require(‘./routes/user’);
var http = require(‘http’);
var path = require(‘path’);
var fs = require(‘fs’);

You should use a function called getAllFileURIs, as in Listing 4, that receives a folder name and a callback function. The getAllFileURIs function will use the folder name to open that folder; later, it will return all the file URIs in that folder.

Listing 4: The getAllFileURIs Function
var getAllFileURIs = function(folder: string, callback: Function): void {
var results = [],
relativePath = folder.substr(8);
fs.readdir(folder, (err, files) => {
if (err) {
callback([]);
};
files.forEach(function(file) {
file = relativePath + ‘/’ + file;
results.push(file);
});
callback(results);
});
};

You can see that I used lambdas in the code and types for the arguments that the function receives. These features come from TypeScript and aren’t currently part of JavaScript.

After you write the getAllFileURIs function, you should add an endpoint called getAllImages on your server. This endpoint uses the getAllFileURIs function to fetch all the URIs for files that exist in the /public/Content/Photos folder. Listing 5 shows what the implementation of this endpoint should look like. In Listing 5, whenever a request arrives to the getAllImages endpoint, an array of image URIs is serialized to JSON format and is written to the response.

Listing 5: Implementing the getAllImages Endpoint
app.get(‘/getAllImages’, (req, res) => {
getAllFileURIs(‘./public/Content/Photos’, (imageUris) => {
res.writeHead(200, { ‘Content-Type’: ‘application/json’ });
res.write(JSON.stringify(imageUris));
res.end();
});
});

Your server code is now ready to run. Be sure to set the generated app.js file as the startup file for the node.js application. Figure 2 shows a running DevConnections photo gallery with only the server implementation. (Notice that there are no photos in the gallery yet.) Now that you have a working server side, you need to create the client side.

Figure 2: DevConnections Photo Gallery with only the Server Implementation

Figure 2: DevConnections Photo Gallery with only the Server Implementation

Creating the Client Side Using JavaScript Libraries

You’ll use two libraries on the client side: jQuery and Galleria. You’re probably already familiar with jQuery; Galleria is a JavaScript library that’s used to create a gallery from an image array. You can download Galleria, or you can use your own gallery library as long as you adjust the code, as I show you later in this article

Setting up the folders. In the public folder that was created by the Express project template, create a Scripts folder that you’ll use to hold all the scripts that the application uses. Under the Scripts folder, add two new folders named app and lib. Put all the application TypeScript files and the generated JavaScript files in the app folder. Put the jQuery and Galleria JavaScript files in the lib folder.

To use JavaScript libraries as though they were created with TypeScript, you need to import the libraries’ declaration files to the project. A declaration file is a file that ends with the .d.ts postfix; it describes the interfaces of the library. Having a declaration file can help the TypeScript environment understand the types included in a typed library. However, not all libraries have a declaration file. A known GitHub repository calledDefinitelyTyped includes most of the major libraries’ declaration files. You should download the jquery.d.ts declaration file and put it under the lib folder. Unfortunately, Galleria isn’t included in DefinitelyTyped. Now you’re ready to create the TypeScript files and use the libraries.

Creating the client-side implementation. The first step in configuring the client side is to create the data structures for Galleria image information and for Galleria configuration options. Create a new TypeScript file in the app folder that exists in the Scripts folder. Call the new file datastructures.ts. Both of the classes you’ll create will be a part of the app.data.structures module. The code in Listing 6 implements the data structures.

The data structure implementation is very simple. The data structures include properties that the application will later use to configure the image gallery.

After you’ve created the data structures, you need to configure the interaction with the server, and you need to fetch the images for the gallery. To accomplish these tasks, you need to implement a data service class. Create a new TypeScript file in the app folder that exists in the Scripts folder. Call the new file dataservice.ts. The data service’s responsibility will be to call the getAllImages endpoint and use the array of image URIs to create Galleria images, as Listing 7 shows.

Listing 7: Implementing a Data Service Class
/// <reference path=”../lib/jquery.d.ts” />
/// <reference path=”datastructures.ts” />
module app.data {
import structures = app.data.structures;
export interface IDataService {
getImages: () => JQueryPromise;
}
export class DataService implements IDataService {
getImages(): JQueryPromise {
var deferred = $.Deferred();
var result: structures.GalleriaImage[] = [];
$.getJSON(“/getAllImages”, {}, (imageUris) => {
$.each(imageUris, (index, item) => {
result.push(new structures.GalleriaImage(new structures.GalleriaImageConfigOptions(item, “”, “”, “My title” + index, “My description” + index, “”)));
});
deferred.resolve(result);
});
return deferred.promise();
}
}
}

As you can see in Listing 7, one of the first steps is to import the app.data.structures module. Later on, you declare an interface that exposes a getImages function. The getImages function returns a JQueryPromise object that will help defer the execution of the getImages operation until the getJSON function returns and runs its success callback. When the getJSON success callback runs, it creates a GalleriaImage object for each image URI that’s part of the array that was returned by the server.

Now that you have data structures and a data service, you need to configure the Galleria object. Create a new TypeScript file in the app folder that exists in the Scripts folder. Call the new file bootstrapper.ts. In the bootstrapper.ts file, create a Bootstrapper class that’s responsible for running the Galleria object, as Listing 8 shows.

Listing 8: Configuring the Galleria Object
/// <reference path=”../lib/jquery.d.ts” />
/// <reference path=”dataservice.ts” />
declare var Galleria;
module app {
import data = app.data;
export interface IBootstrapper {
run: () => void;
}
export class Bootstrapper implements IBootstrapper {
run() {
this.getData().then((images) => {
Galleria.configure({
imageCrop: true,
transition: ‘fade’,
dataSource: images,
autoplay: true
});
Galleria.run(‘#galleria’);
});
}
getData(): JQueryPromise {
var dataService = new data.DataService();
return dataService.getImages();
}
}
}

One of the interesting things in the implementation is the call to declare var Galleria.Because Galleria doesn’t have a declaration file, you need to declare its object. This is where the declare keyword becomes very handy. You use the declare keyword to inform the TypeScript runtime that the declared variable is dynamic and should be used with theany type.

The last part of the puzzle is the app.ts file. You need to create this file in the app folder that exists in the Scripts folder. Don’t be confused between the app.ts file of node.js and this app.ts file, which is used to run the application. The code in Listing 9 implements the client-side app.ts file.

Listing 9: Implementing the Client-Side app.ts File
/// <reference path=”bootstrapper.ts” />
module app {
// start the app on load
window.addEventListener(“DOMContentLoaded”, (evt) => {
var bootstrapper = new app.Bootstrapper();
bootstrapper.run();
}, false);
}

Now that all the parts are in place, the final result is an image gallery (see Figure 3). You can put images in the Images folder, which exists under the Content folder. You candownload the complete application that I used to create the DevConnections photo gallery.

Figure 3: Final DevConnections Photo Gallery

Figure 3: Final DevConnections Photo Gallery

The TypeScript Advantage

In this article you learned how to use TypeScript to build a simple application. TypeScript can help you bridge the missing JavaScript features that will eventually be available in ECMAScript 6. TypeScript allows you to write large-scale JavaScript code and maintain it more easily. You can use TypeScript both in the application front end and in the application back end with frameworks and environments that run JavaScript.

[.NetWorld] Flushing in ASP.NET MVC

The Setting

Before the beginning of this decade, Steve Souders released two seminal books on the topic of web performance: High Performance Web Sites and Even Faster Web Sites. The findings and subsequent suggestions that came out of those books changed the face of web development and have been codified into several performance analysis tools including Yahoo YSlow and Google PageSpeed.

High Performance Web Sites Even Faster Web Sites

Most professional web developers that I’ve met over the past five years are familiar with Souder’s recommendations and how to implement them in ASP.NET MVC. To be fair, they aren’t that difficult:

  • HTTP Caching and Content Compression can both be enabled simply via a few settings in web.config.
  • Layout pages make it easy to put stylesheets at the top of a page and scripts at the bottom in a consistent manner.
  • The Microsoft.AspNet.Web.Optimization NuGet package simplifies the ability to combine and minify assets.
  • And so on, and so forth…

The recommendation to “Flush the Buffer Early” (covered in depth in chapter 12 of Even Faster Web Sites), however, is not so easy to implement in ASP.NET MVC. Here’s an explanation of the recommendation from Steve’s 2009 blog post:

Flushing is when the server sends the initial part of the HTML document to the client before the entire response is ready. All major browsers start parsing the partial response. When done correctly, flushing results in a page that loads and feels faster. The key is choosing the right point at which to flush the partial HTML document response. The flush should occur before the expensive parts of the back end work, such as database queries and web service calls. But the flush should occur after the initial response has enough content to keep the browser busy. The part of the HTML document that is flushed should contain some resources as well as some visible content. If resources (e.g., stylesheets, external scripts, and images) are included, the browser gets an early start on its download work. If some visible content is included, the user receives feedback sooner that the page is loading.

A few months ago Steve revisited this guidance and provided examples of the difference that flushing can make to an application’s performance. His post inspired me to try the same on an ASP.NET MVC project that I’m working on, which led to this post.

The Conflict

Since .NET 1.1, ASP.NET has provided a mechanism to flush a response stream to the client with a simple call to HttpResponse.Flush(). This works quite well when you are incrementally building up a response, but the architecture of MVC, with its use of the command pattern, doesn’t really allow for this. (At least not in a clean manner.) Adding a call to Flush() inside a view doesn’t do much good.

@{
     Response.Flush();
}

This is because MVC doesn’t execute the code in the view until all the other work in the controller has completed – essentially the opposite of what the czar of web performance recommends.

The Climax

Because I’m a believer that #PerfMatters, I decided to take matters into my own hands to see if I could do anything better.

First, I realized that I could can get around a few issues by leveraging partial results, manually executing and flushing them, like so:

public ActionResult FlushDemo()
{
       PartialView("Head").ExecuteResult(ControllerContext);
       Response.Flush();

       // do other work
       return PartialView("RemainderOfPage");
}

I think that looks pretty ugly, so I’ve taken things a step farther and removed the cruft around executing the result by creating a base controller with its own Flush()method:

public class BaseController : Controller
{
     public void Flush(ActionResult result)
     {
         result.ExecuteResult(ControllerContext);
         Response.Flush();
     }
}

I think my new Flush() method clarifies the intent in the action method:

public ActionResult FlushDemo()
{
     Flush(PartialView("Head"));

     // do other work
     return PartialView("RemainderOfPage");
}

What I’d really like to be able to do is leverage the yield keyword. Yield seems like the natural language and syntax to express this. I was able to cobble together this example:

public IEnumerable<ActionResult> Test()
{
      yield return PartialView("Header");
      Thread.Sleep(2000); // or other work

      yield return PartialView("Lorem");
      Thread.Sleep(2000); // or other work

      yield return PartialView("Vestibulum");
      Thread.Sleep(2000); // or other work

      yield return PartialView("Sed");
      Thread.Sleep(2000); // or other work

      yield return PartialView("Footer");
}

I got that working with a pretty ugly hack, but leveraging the yield keyword andIEnumerable<ActionResult> like this should theoretically be possible by making a few changes to MVC’s default action invoker, no hack necessary.  Unfortunately, C# throws a few curve balls at this since you can’t combine the usage of yield withasync/await – which I think would be a pretty common usage scenario.

The Resolution?

It looks like splitting up a layout file into multiple partial views and using my Flush()helper method is the best that we can do right now.

Unfortunately,

  • Yielding multiple views isn’t currently supported by MVC, and even if it was it would be incompatible with the current C# compiler.
  • Partial views are the best we can get to break up a response into multiple segments – which is painful. It’d be nice if I could ask Razor to render just a section of a layout page, which would reduce the need for partial views.

I’m hoping that the ASP.NET team, or my readers, can come up with a better way to handle flushing in the future, but I wanted to at least walk you through what your options are today.