Làm thế nào để xử lý giá trị Null trong biểu thức truy vấn

 

Ví dụ này cho thấy làm thế nào để xử lý các giá trị null có thể có trong bộ sưu tập nguồn. Một bộ sưu tập các đối tượng đó như là một IEnumerable<T> có thể chứa các yếu tố có giá trị null. Nếu nguồn là một bộ sưu tập vô giá trị hoặc có một phần tử có giá trị null, và query của bạn không xử lý các giá trị null, NullReferenceException sẽ được đẩy ra ngoài khi bạn thực hiện câu truy vấn.

Bạn có thể bảo vệ mã để tránh một ngoại lệ tham chiếu null như trong ví dụ sau đây:

 

var query1 =  from c in categories
       where c != null
       join p in products on c.ID equals
               (p == null ? null : p.CategoryID)
       select new { Category = c.Name, Name = p.Name };

 

Trong ví dụ trước, các nơi mệnh đề lọc ra tất cả các yếu tố null trong thứ tự danh mục. Kỹ thuật này được độc lập của việc kiểm tra null trong mệnh đề join. Các biểu thức điều kiện với null trong ví dụ này hoạt động bởi vì Products.CategoryID là kiểu int? đó là viết tắt cho Nullable<int>.

Trong một mệnh đề join, nếu chỉ có một trong các phím so sánh là một loại giá trị nullable, bạn có thể bỏ các kia với một loại nullable trong biểu thức query. Trong ví dụ sau đây, giả sử là EmployeeID là một cột chứa giá trị kiểu int?:

 

void TestMethod(Northwind db)
{
       var query = from o in db.Orders
              join e in db.Employees
                     on o.EmployeeID equals (int?)e.EmployeeID
              select new { o.OrderID, e.FirstName };
}

 

 

Làm Thế Nào Config Log4Net Trong C#

Log4net là gì?

Log4net là một công cụ giúp người lập trình ghi lại những thông tin trong lúc chạy ứng dụng. Nó chính là một phiên bản chuyển thể từ log4j và vẫn tiếp tục được phát triển kể từ năm 2001. Trong trường hợp ứng dụng của bạn có lỗi mà vẫn không tìm được nguyên nhân, log4net có thể là vị cứu tinh để giúp bạn xác định nơi gây lỗi. Ngoài ra, Log4net còn có thể thay đổi trạng thái log lúc chương trình chạy mà không cần ngừng chương trình. Bên cạnh đó, khi sử dụng log4net sẽ không ảnh hưởng đáng kể đến performance của ứng dụng, log4net còn được thiết kế với tính flexibility rất cao, chúng ta có thể mở rộng và thêm thắt những thứ mình muốn vào thư viện log4net, chẳng hạn như cách thức log, định dạng log,

Sử dụng như thế nào?

Trong bài viết này, tôi sẽ giới thiệu cách sử dụng log4net cho một window application và cách config cho log4net ghi thông tin log ra file bằng một file config. Thực ra đối với web application thì cách sử dụng hoàn toàn tương tự. Chỉ có một số trường hợp file log của bạn không sinh ra được vì không đủ quyền. Như các bạn biết thì Web application chạy dưới 1 process bằng quyền của user ASPNET trong Windows, dó đó nếu user này không đủ quyền ghi file vào folder web của bạn thì file log tương ứng cũng có thể không được tạo ra.

Hãy download version mới nhất của log4net từ website apache. và add reference vào project của bạn như hình sau:

Sau khi bạn đã reference Log4net vào project của mình hoàn chỉnh, các bước còn lại bạn tiếp tục config để project của bạn hiểu Log4Net ở đâu. Để project hiểu bạn cần config code mỗi khi project gọi Log4Net, như vậy thì rất dài dòng và phức tạp vì phải gọi ��i gọi lại nhiều lần. Cách đơn giản hãy tạo một class dùng chung và bạn có thể gọi bất cứ đâu mà bạn muốn :

public static class LogService
{
      #region Members
      private static readonly ILog logger = LogManager.GetLogger(typeof(LogService));
     #endregion
      #region Constructors
      static LogService()
     {
          BasicConfigurator.Configure();
          XmlConfigurator.Configure();
     }
     #endregion
     #region Methods   
    public static void WriteLog(LogLevel logLevel, String log)
    {
         if (logLevel.Equals(LogLevel.DEBUG))
             logger.Debug(log);
        else if (logLevel.Equals(LogLevel.ERROR))
            logger.Error(log);
        else if (logLevel.Equals(LogLevel.FATAL))
            logger.Fatal(log);
        else if (logLevel.Equals(LogLevel.INFO))
            logger.Info(log);
        else if (logLevel.Equals(LogLevel.WARN))
            logger.Warn(log);
    }
    #endregion
}

Bây giờ chúng ta đã có class dùng chung trong project của bạn, câu hỏi ở đây là chúng ta sẽ gọi chúng như thế nào? và còn config nào nữa ?. Câu trả lời cho các bạn là còn rất nhiều bạn cứ từ từ và xem tiếp theo. Trước tiên bạn xem project của bạn thuộc một thể loại nào Application hay Web, không sao dù là project nào thì đều có file config riêng cho nó.

Application thì ta có App.config

Web thì ta có Web.config.

Bạn hãy thêm config này vào trong config file của bạn :

Trong file cấu hình này, tôi sử dụng RollingFileAppender. Có rất nhiều loại Appender được xây dựng sẵn trong thư viện log4net. Mỗi loại sẽ có công dụng ghi nội dung log vào một nơi khác nhau. Trong đó RollingFileAppender là được sử dụng nhiều nhất và cũng dễ sử dụng nhất. Tôi sẽ giải thích những gì tôi nghĩ là khó hiểu nhất

<file value="Log4netSampleLog.txt">

Thông tin log của chúng ta sẽ được ghi vào file Log4netSampleLog.txt, file này sẽ nằm ở thư mục chạy của ứng dụng, cùng cấp với file exe và file .config của chúng ta. Nếu muốn nó lưu file vào chỗ khác chúng ta có thể hardcode đường dẫn ở đây.

<maxsizerollbackups value="3" />

Dữ liệu log sẽ được ghi vào file, vì ta đang sử dụng là RollingFileAppender, nên khi kích thước file vượt quá một mức nào đó thì nó sẽ đổi tên file cũ và ghi vào file mới. Tổng số lượng file tối đa sẽ là 10 và những file cũ nhất sẽ bị xóa nếu số lượng file vượt quá 3.

<maximumfilesize value="1MB">

Kích thước file log tối đa sẽ là 1MB.

Layout: Đây là phần khá thú vị, những text log mà chúng ta ghi ra sẽ kèm thêm một số thông tin theo như phần định dạng trong layout như ngày tháng, threadId, className, ... Các bạn có thể tùy biến phần layout này để được log output dễ nhìn nhất.

<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
<layout>

Level: Level mặc định sẽ là Debug cho mọi nơi có sử dụng log trong chương trình của bạn. Nghĩa là nếu bạn khai báo như hình, thì mọi chỗ bạn log đều được ghi xuống file vì level DEBUG là level thấp nhất, nhưng nếu chỗ này bạn để là ERROR thì chỉ có những log với level cao hơn hoặc bằng ERROR mới được ghi xuống file. Khi deploy chương trình cho khách hàng, thường thì chúng ta sẽ để level default là ERROR, khi sử dụng có lỗi ta sẽ yêu cầu khách hàng sử lại thành DEBUG nếu cần thiết.

<root>
<level value="DEBUG" />
<appender-ref ref="RollingLogFileAppender" />
</root>

- Thông thường người ta sử dụng full name của class (kèm theo đầy đủ namespace) để dùng như loggerName. Cách dùng này rất hợp lý vì chúng ta sẽ biết đoạn log của mình sinh ra từ class.nào. Để ghi Log bạn cần phải xác định rằng bạn ghi cái gì và ghi như thế nào?

Để ghi thông tin bạn làm như sau:

Để ghi lỗi bạn làm như sau :

Còn nhiều và nhiều cách config cho Log4Net bạn có thể tham khao các cách config tại trang wen của nó. 

Chúc bạn thành công.

Cấu hình Log4net như thế nào (Phần 1)?

 

Bài viết này trình bày các cấu hình ví dụ cho việc xây dựng trong appenders. Các cấu hình được thiết kế để làm việc với các log4net.Config.DOMConfigurator và log4net.Repository.Hierarchy.Hierarchy này.

Những ví dụ này không có nghĩa là cấu hình đầy đủ cho các appenders. Đối với một danh sách đầy đủ các thông số có thể thể chỉ định cho từng appender và chi tiết hơn trên mỗi tùy chọn xem tài liệu SDK cho appender này.

AdoNetAppender: Để biết chi tiết đầy đủ xem tham khảo SDK mục: log4net.Appender.AdoNetAppender.

Những cấu hình của AdoNetAppender phụ thuộc vào nhà cung cấp lựa chọn cho các cơ sở dữ liệu mục tiêu. Dưới đây là một số ví dụ.

MS SQL Server: Ví dụ sau đây cho thấy làm thế nào với cấu hình các AdoNetAppender để log tin nhắn với một cơ sở dữ liệu SQL Server. Những sự kiện được viết bằng lô 100 (BufferSize). ConnectionType quy định cụ thể tên kiểu đủ điều kiện cho các System.Data.IDbConnection sử dụng để kết nối với cơ sở dữ liệu. ConnectionString là cơ sở dữ liệu nhà cung cấp cụ thể. CommandText là cả một tuyên bố đã chế biến hoặc thủ tục lưu trữ, trong trường hợp này nó có một prepared statement. Mỗi tham số lập báo cáo hoặc thủ tục lưu trữ được chỉ định bằng tên nó, kiểu cơ sở dữ liệu và cách bố trí mà renders giá trị cho tham số.

Định nghĩa bảng cơ sở dữ liệu có:

CREATE TABLE [dbo].[Log] (
     [Id] [int] IDENTITY (1, 1) NOT NULL,
     [Date] [datetime] NOT NULL,
     [Thread] [varchar] (255) NOT NULL,
     [Level] [varchar] (50) NOT NULL,
     [Logger] [varchar] (255) NOT NULL,
     [Message] [varchar] (4000) NOT NULL,
     [Exception] [varchar] (2000) NULL
)

Những cấu hình appender có:

 

<appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
   <bufferSize value="100" />
       <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
       <connectionString value="data source=[database server];initial catalog=[database  name];integrated security=false;persist security info=True;User ID=[user];Password=[password]" />
       <commandText value="INSERT INTO Log ([Date],[Thread],[Level],[Logger],[Message],[Exception]) VALUES (@log_date, @thread, @log_level, @logger, @message, @exception)" />
       <parameter>
          <parameterName value="@log_date" />
          <dbType value="DateTime" />
          <layout type="log4net.Layout.RawTimeStampLayout" />
       </parameter>
       <parameter>
          <parameterName value="@thread" />
          <dbType value="String" />
          <size value="255" />
          <layout type="log4net.Layout.PatternLayout">
              <conversionPattern value="%thread" />
          </layout>
      </parameter>
      <parameter>
          <parameterName value="@log_level" />
          <dbType value="String" />
          <size value="50" />
          <layout type="log4net.Layout.PatternLayout">
                 <conversionPattern value="%level" />
           </layout>
       </parameter>
       <parameter>
              <parameterName value="@logger" />
              <dbType value="String" />
              <size value="255" />
              <layout type="log4net.Layout.PatternLayout">
                    <conversionPattern value="%logger" />
              </layout>
       </parameter>
       <parameter>
              <parameterName value="@message" />
              <dbType value="String" />
              <size value="4000" />
              <layout type="log4net.Layout.PatternLayout">
                   <conversionPattern value="%message" />
              </layout>
        </parameter>
        <parameter>
               <parameterName value="@exception" />
               <dbType value="String" />
               <size value="2000" />
               <layout type="log4net.Layout.ExceptionLayout" />
         </parameter>
</appender>

 

 

Tìm hiểu về log4net

 

log4net là một công cụ để giúp đỡ các lập trình ghi lại báo cáo và xuất ra một loạt các mục tiêu. Khi có vấn đề với các ứng dụng, nó thật sự hữu ích có thể tìm ra vấn đế một cách chính xác. Với log4net có thể để cho phép đăng nhập tại thời gian chạy mà không sửa đổi các ứng dụng hệ nhị phân. Những gói log4net được thiết kế để báo cáo bản ghi có thể vẫn còn trong mã shipped mà không bị một chi phí hoạt động cao. Khác...

Delegate và Event trong Csharp

Khái niệm delegate được hiểu như là một con trỏ hàm (method). Thực tế là một method nó cũng có 1 vùng nhớ xác định trên Ram và khi biết được địa chỉ của vùng nhớ này thì mình có thể gọi method thực hiện, bình thường mình gọi method thông qua đối tượng (instance) hoặc tên class (nếu là method static) và tên method. Như vậy một delegate được hiểu nôm na là một kiểu dùng để lưu trữ 1 hay nhiều địa chỉ method mà những method này phải cùng prototype (gồm kiểu trả về và danh sách các tham số). Khi ta có một biến delegate đang nắm giữ danh sách các method (có cùng prototype với nó) thì chỉ cần khởi động biến này tất cả các danh sách method đó sẽ được thực hiện lần lượt mà ta không cần quan tâm đến tên method đó nữa.

Delegate rất có ý nghĩa khi kết hợp với event, như bác sangcn đã đề cập thì event là một thể hiện đặc biệt của delegate. Theo khái niệm thì event là một thông điệp được gửi tới những đối tượng đã đăng ký trước đó để thực hiện hành động nào đó kèm theo khi thông điệp đó được gửi tới (nghĩa là sự kiện đó x���y ra). Ví dụ, khi chúng ta click chuột vào 1 nút (button) nào đó trên một form (cửa sổ ứng dụng), nghĩa là lúc này đối tượng nút sẽ truyền một thông điệp (phát ra sự kiện nhấn chuột) cho đối tượng form để gọi tới method mà form này đã đăng ký nhận thông điệp khi sự kiện nhấn chuột xảy ra.

Một ứng dụng cụ thể để hiểu mục đích sử dụng delegate event đó là chúng ta viết một class clock (đồng hồ), và một yêu cầu rằng khi người ta sử dụng đối tượng clock này thì muốn nhận một thông điệp (sự kiện) EndTime (hết giờ) để thực hiện một hành động gì đó kèm theo sự kiện này. Ví dụ ta viết một chương trình game đoán chữ và có giới hạn thời gian cho người chơi là 10 giây, hết thời gian này thì chương trình sẽ thông báo "Time over" chẳng hạn. Như vậy, ta sẽ cần ít nhất 2 class là Game và Clock. Chúng ta hãy xem mã nguồn để thể hiện ví dụ này.

public class Clock
{
    private int _second;
    // Định nghĩa một delegate để trỏ vào những method có kiểu không đối số, không kiểu trả về
    public delegate void TimeOver();
    // Khai báo 1 event thuộc kiểu delegate trên
    public event TimeOver EndTime;
    public Clock(int second)
    {
        _second = second;
    }
    public int Second
    {
        get { return _second; }
        set { _second = value; }
    }
    /// 
    /// Method đếm lùi thời gian cho đến khi _second = 0 thì kết thúc và báo lên sự kiện EndTime
    /// 
    public void Timedown()
    {
        do
        {
            _second--;
            Thread.Sleep(1000);
        }
        while (_second > 0);
        // trước khi gọi event hoặc delegate thì cần kiểm tra biến có null không (nghĩa là có chứa địa chỉ
        // của method nào không) nếu khác null (có chứa 1 ít nhât 1 method) thì mới gọi.
        if (EndTime != null)
            EndTime(); // gọi thực hiện các method đã đăng ký sự kiện.
    }
}
class Game
{
    /// 
    /// Method dùng để thực hiện hành động kèm theo khi sự kiện EndTime (delegate TimeOver) xảy ra
    /// 
    public void GameOver()
    {
        Console.WriteLine("Game over");
    }
}

class Program
{
    static void Main(string[] args)
    {
        Clock c = new Clock(10);
        Game g = new Game();
        // Đăng ký method thực hiện hành động kèm theo khi có sự kiện EndTime xảy ra
        c.EndTime += new Clock.TimeOver(g.GameOver);
        ThreadStart ts = new ThreadStart(c.Timedown);
        Thread ChildThread = new Thread(ts);
        ChildThread.Start();
        Console.WriteLine("Waiting about 10 second...");
    }
}

Chủ đề này là một chủ đề lớn và rất hay vì thế sẽ có video để chúng ta tìm hiểu sâu hơn nữa. Hy vọng bạn cũng phần nào nắm được. Tôi gửi link download mã nguồn cho ví dụ trên để bạn tiện tham khảo.

DemoEvent.rar (23,46 kb)

Nguồn: http://www.hoctinhoctructuyen.com/Questions?page=3&TypeSearch=-1