2010-01-25 17 views

Trả lời

94

Tôi có thể xem từ các bài đăng trên diễn đàn và blog ở khắp mọi nơi mà nhiều người khác trước khi tôi tìm kiếm một cách để nhận các câu lệnh SQL khi chúng được chuẩn bị để thực thi. Câu trả lời thường là một cái gì đó dọc theo dòng "bạn không thể", hoặc "bạn không nên".

Cho dù tôi có nên hay không, đó là những gì tôi muốn.

Sau nhiều giờ tìm kiếm, điều tra và không thành công, và cuối cùng tôi đã nghĩ ra điều này.

Viết lên một đánh chặn:

using NHibernate; 
using System.Diagnostics; 

public class SqlStatementInterceptor : EmptyInterceptor 
{ 
    public override NHibernate.SqlCommand.SqlString OnPrepareStatement(NHibernate.SqlCommand.SqlString sql) 
    { 
     Trace.WriteLine(sql.ToString()); 
     return sql; 
    } 
} 

Tất nhiên, bạn không cần phải Trace.WriteLine() đây, bạn có thể viết nó vào một tập tin nhật ký, hoặc bất cứ điều gì khác mà bạn cần.

Trong quản lý kết nối của bạn, treo lên Interceptor của bạn như vậy:

protected virtual void Configure(FluentConfiguration config) 
{ 
    config.ExposeConfiguration(x => 
            { 
             x.SetInterceptor(new SqlStatementInterceptor()); 
            }); 
} 

Nó không phải là phức tạp. Từ quan điểm của tôi, chắc chắn dễ dàng hơn là cố gắng để có được tất cả các XML này được đẩy thông qua Fluent sang NHibernate - vì Fluent trừu tượng hóa tệp XML đi.

Hãy nhớ, bạn chỉ có thể có một Interceptor duy nhất - vì vậy bạn có thể cần phải tích hợp tính năng này với Bộ chặn đánh chặn hiện tại của bạn, nếu bạn đã có. Trên ghi chú đó, bạn có thể muốn đặt tên cho nó rộng hơn - ví dụ: MyAppInterceptor, để không ngụ ý một mục đích cụ thể, bởi vì bạn có thể muốn thêm các tính năng khác vào nó sau này.

Hy vọng điều này hữu ích cho người khác! :-)

+0

giải pháp tuyệt vời, đơn giản như địa ngục và nó chỉ hoạt động, thêm nó vào của tôi kiểm tra nhà máy phiên mặc dù có thể chỉ cần thêm với #if DEBUG. Cảm ơn! –

+4

Có thể nó cũng có thể điền vào các tham số? Tôi nhận được '?' (Dấu hỏi) thay vì các giá trị trong các truy vấn như 'SELECT * FROM MyObject WHERE Id =?'. Tôi thấy có một 'IEnumerable NHibernate.SqlCommand.SqlString.GetParameters()' –

+1

@Mike thay thế 'sql.ToString()' bằng 'base.OnPrepareStatement (sql)' –

33

Bạn có thể muốn sử dụng log4net, không phải ShowSql. Dưới đây là một số cấu hình để gửi các truy vấn để gỡ lỗi:

<configSections> 
    <section name="log4net" 
    type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" /> 
    </configSections> 

    <log4net debug="false"> 
    <appender name="WindowsDebugOutput" type="log4net.Appender.DebugAppender, 
     log4net"> 
     <layout type="log4net.Layout.PatternLayout,log4net"> 
     <param name="ConversionPattern" 
       value="%d{ABSOLUTE} %-5p %c{1}:%L - %m%n" /> 
     </layout> 
    </appender> 

    <logger name="NHibernate.SQL" additivity="false"> 
     <level value="DEBUG" /> 
     <appender-ref ref="WindowsDebugOutput" /> 
    </logger> 
    </log4net> 

Và sau đó gọi này từ mã của bạn trước khi mở một phiên NHibernate:

log4net.Config.XmlConfigurator.Configure(); 

Khi bạn thêm một tham chiếu đến DLL log4net, hãy chắc chắn để đặt thuộc tính "Sao chép Địa phương" thành "true".

Đây không phải là đặc trưng cho FluentNHibernate, nó hoạt động giống nhau trong bất kỳ biến thể nào của NHibernate.

+0

Câu hỏi khó hiểu, nhưng, nơi đặt tệp cấu hình này trong dự án winforms?Rất nhiều trang web tài liệu của Hibernate bị hỏng và tôi không thể tìm thấy nơi để đưa thông tin XML này. Cảm ơn. –

+1

@Mike - nó sẽ đi vào app.config trong thư mục gốc của dự án, được sao chép vào thư mục bin là .exe.config tại thời gian biên dịch. –

+1

Thật tuyệt khi có câu trả lời tại một nhận xét về câu trả lời hơn 3 tuổi! Cảm ơn thời gian lớn! –

11

Tôi chưa thử với SQL Server, nhưng với SQLite, đoạn mã sau sẽ hiển thị SQL được tạo trong cửa sổ Đầu ra (Trình đơn gỡ lỗi -> Windows -> Đầu ra, trong VS2008).

Hộp kết hợp "Hiển thị đầu ra từ:" trong cửa sổ Đầu ra phải được đặt thành "Gỡ lỗi" - VS2008 đã làm điều đó cho tôi một cách tự động.

  sessionFactory = Fluently.Configure() 
       .Database(SQLiteConfiguration.Standard 
          .UsingFile(DbFile) 
          // Display generated SQL in Output window 
          .ShowSql() 
         ) 
       .Mappings(m => m.AutoMappings.Add(GetAutoPersistenceModel())) 
       .BuildSessionFactory() 
       ; 

Cảnh báo - bật tính năng này có thể làm chậm hoạt động đáng kể.

+3

Cửa sổ đầu ra trong Visual Studio hiển thị đầu ra Console, Debug và Trace. Phương thức ShowSql ghi vào Console, không phải Debug hoặc Trace. Đề xuất của bạn không khác với những gì anh ta nói anh ta đã làm. –

+0

@Michael -I vừa kiểm tra lại điều này, và nó hoạt động CHÍNH XÁC như mô tả! Có thể một sự khác biệt trong việc thực hiện giao diện FNH với SQLite so với SQL Server? –

+1

Đó không phải là "Gỡ lỗi" giống nhau (thông báo không có tùy chọn cho "Dấu vết" hoặc "Bảng điều khiển"). :) Để xem nếu nó thực sự là văn bản để gỡ lỗi, sử dụng một cái gì đó như http://technet.microsoft.com/en-us/sysinternals/bb896647.aspx –

Các vấn đề liên quan