2011-01-28 12 views
9

पर NULL लिखें I ASP.Net अनुप्रयोग में लॉग इन करने और Microsoft SQL सर्वर के साथ डेटाबेस लक्ष्य का उपयोग करने के लिए NLog का उपयोग कर रहा हूं।एनएलओजी - वैकल्पिक डेटाबेस कॉलम

मेरे पास कुछ लॉगिंग पैरामीटर हैं जो वैकल्पिक हैं और हमेशा निर्दिष्ट नहीं हैं। मैं इन्हें प्रदान नहीं करते समय उन्हें शून्य के रूप में लिखा जाना चाहूंगा, हालांकि NLog हमेशा उन्हें खाली तार के रूप में लिखते हैं।

क्या डिफ़ॉल्ट रूप से शून्य को लिखने के लिए इसे कॉन्फ़िगर करने का कोई तरीका है?

रेफरी: https://github.com/nlog/NLog/wiki/Database-target

उत्तर

2

[संपादित करें]

हो सकता है कि क्या मैं नीचे का प्रस्ताव लॉग इन करने के लिए एक डेटाबेस प्रक्रिया का उपयोग करने के लिए एक सम्मिलित करें कथन का उपयोग से बदलने के लिए किया जाएगा की तुलना में अधिक स्पष्ट समाधान। यदि आप डेटाबेस प्रक्रिया का उपयोग करते हैं तो आप खाली स्ट्रिंग से स्विजलिंग को अपने आप को कम करने के लिए संभाल सकते हैं। मुझे यकीन नहीं है कि आप एनएलओजी के डाटाबेस लक्ष्य के साथ डेटाबेस प्रक्रिया का उपयोग कर सकते हैं। Log4net इसका समर्थन करता है इसलिए मेरा अनुमान यह है कि एनएलओजी भी करता है।

यहां एक उदाहरण है (लिंक किए गए प्रश्न के उत्तर में) मैंने संग्रहीत प्रक्रिया का उपयोग कर डेटाबेस पर लॉग इन करने के लिए एनएलओजी का उपयोग करने वाले किसी से कॉन्फ़िगरेशन पाया है।

http://nlog-forum.1685105.n2.nabble.com/Using-a-stored-procedure-for-the-DB-Target-td2621725.html

मैं यहाँ देखें:

http://nlog.codeplex.com/workitem/5418

एक शिकायत यह है कि यह काम नहीं करता (कम से कम NLog 2.0 बीटा में)। दो उदाहरण के बीच

एक अंतर यह है कि काम कर रहे उदाहरण का उपयोग करता है "कार्यकारी LoggingProcedureName ..." जबकि nonworking एक का उपयोग करता "LoggingProcedureName ..."

आशा इस मदद करता है।

[समाप्ति संपादित करें]

मैं क्यों NLog अशक्त या कैसे रिक्त स्ट्रिंग के बजाय NLog लिखने अशक्त बनाने के लिए के बजाय emptry तार लिखते हैं इस पर टिप्पणी नहीं कर सकते, लेकिन मुझे आश्चर्य है कि अगर आप वे जिस तरह से आप यह काम कर सकता है अतिरिक्त विन्यास के माध्यम से चाहते हैं?

लॉगिंग पैरामीटर वैकल्पिक कब होते हैं? क्या आपके कोड में कुछ स्थान हैं जहां आप हमेशा कुछ मान और अन्य स्थानों को लॉग करते हैं जहां आपने कभी कुछ मूल्यों को लॉग नहीं किया है? क्या आप (डेवलपर के रूप में) जानते हैं कि कौन से वैकल्पिक पैरामीटर लागू होते हैं जिसमें आपके आवेदन के अनुभाग शामिल हैं?

क्या आप एकाधिक डेटाबेस लक्ष्य कॉन्फ़िगर कर सकते हैं, प्रत्येक निर्दिष्ट "दाएं" पैरामीटर के साथ? फिर आप लॉगर्स को विशिष्ट डेटाबेस लक्ष्य पर इंगित कर सकते हैं जो कोड स्थान के लिए उपयुक्त है।

कहें कि आपका एप्लिकेशन कोड (नामस्थान द्वारा) को कोड में विभाजित किया गया है (आमतौर पर) "पहले", "दौरान" और "बाद" निष्पादित करता है।

"पहले" कोड में, आप पैरामीटर ए लॉगिंग कर रहे हैं। "दौरान" कोड में, आप पैरामीटर बी लॉगिंग कर रहे हैं। "बाद में" कोड में, आप पैरामीटर सी लॉगिंग कर सकते हैं।

DateTime, Logger, LogLevel, A, B, C, Message, Exception 

अभी आप एक डाटाबेस लक्ष्य है कि हर प्रवेश करने बयान के लिए उन मूल्यों के सभी सम्मिलित करता है: तो, अपने प्रवेश मेज की तरह कॉलम हो सकता है।

क्या होगा यदि आप तीन डाटाबेस लक्ष्य है कि इतनी तरह मान सम्मिलित है:,

<rules> 
    <logger name="Before.*" minlevel="Trace" writeTo="databaseA" /> 
    <logger name="During.*" minlevel="Trace" writeTo="databaseB" /> 
    <logger name="After.*" minlevel="Trace" writeTo="databaseC" /> 
    </rules> 

जाहिर है इस के साथ कई समस्याएं हो सकता है: आप इस तरह अपने अनुभाग कुछ कॉन्फ़िगर कर सकता है

DataTime, Logger, LogLevel, A, Message, Exception 
DataTime, Logger, LogLevel, B, Message, Exception 
DataTime, Logger, LogLevel, C, Message, Exception 

विचार:

  1. यह आपके लॉग को विभाजित करने के लिए संभव (या आसान) हो सकता है पैरामीटर के "वैकल्पिकता" से मेल खाने के लिए तैयार है।

  2. इस व्यवहार्य बनाने के लिए वैकल्पिक पैरामीटर के बहुत से संयोजन हो सकते हैं (शायद 1 के समान दोष)।

  3. एक समय में डेटाबेस लक्ष्यों को सक्रिय करने का एक अच्छा विचार नहीं हो सकता है। शायद यह प्रदर्शन के मुद्दों का कारण होगा।

ठीक है, मेरे पास यह सब कुछ है। मुझे नहीं पता कि मेरा विचार भी काम करेगा, अगर यह व्यावहारिक है तो बहुत कम।

शायद बेहतर समाधान एनएलओजी के लिए प्रत्येक डेटाबेस पैरामीटर पर अतिरिक्त संपत्ति की अनुमति देने के लिए होगा जो आपको "खाली स्ट्रिंग के बजाय शून्य भेजें" कहने की अनुमति देगा।

मुझे लगता है कि मुझे सुझाव देना चाहिए कि आप इस प्रश्न को NLog forum में भी पूछना चाहेंगे। उस मंच पर "क्रेग" ने आज पहले (या समान) प्रश्न पूछा। शायद आप क्रेग हैं।

+0

मैं फ़ोरम पर क्रेग उपयोगकर्ता हूं। विचारों के लिए धन्यवाद, मैं पहले से ही अपने नलॉग डेटाबेस लक्ष्यों के लिए संग्रहीत प्रक्रिया का उपयोग कर रहा हूं, इसलिए आने वाले पैराम पर खाली तारों के लिए परीक्षण और नल लिखने की संभावना है कि मैं जिस तरह से जाऊंगा, मैं बस आपके द्वारा प्रदान किए गए विकल्पों की तलाश कर रहा था, धन्यवाद विकल्पों के लिए। – cweston

6

एनएलओजी पैरामीटर मूल्य बनाने के लिए स्ट्रिंगबिल्डर का उपयोग करता है। यहां तक ​​कि यदि कोई पैरामीटर निर्दिष्ट नहीं है, तो यह बिल्डर के रूप में मान को प्रारंभ करता है। ToString() जो खाली स्ट्रिंग है।

आप इस तरह अपने CommandText बदल सकती है:

INSERT INTO [dbo].[log] ([message], [optional]) 
VALUES 
(
    @message, 
    case 
     when len(@optional) = 0 then null 
     else @optional 
    end 
) 

हालांकि यह मेरे लिए एक हैक की तरह लगता है। मुझे आशा है कि एक बेहतर समाधान होगा।

+0

इसके लिए धन्यवाद, मैं खाली स्ट्रिंग को शून्य पर फ़िल्टर करने के लिए अपनी संग्रहीत प्रक्रिया के भीतर एक समान दृष्टिकोण का उपयोग कर रहा हूं, हालांकि मैं मानता हूं कि यह एक काम है। उम्मीद है कि वे भविष्य में इस कार्यक्षमता को लागू करेंगे। (सुझाव के लिए +1।) – cweston

+0

हाँ, यह थोड़ा हैकी है, लेकिन यह काम करता है। धन्यवाद :) –

11

यह एक पुरानी सवाल है, लेकिन एक छोटे से 'hacky' मैं अपने खुद के जो मैं इसे पर विचार देना चाहता था दिया समाधान की वजह से कर रहे हैं जिस तरह से अधिक एक डाटाबेस प्रक्रिया से लागू करने के लिए सरल और अधिक सुरुचिपूर्ण वह यह है कि एक मामले का उपयोग कर ।

आप NULLIF फ़ंक्शन के साथ NULL लिखने का प्रयास कर सकते हैं जो 2 अभिव्यक्तियों की तुलना करता है और यदि वे बराबर होते हैं तो NULL लौटाता है, अन्यथा यह पहली अभिव्यक्ति (msdn NULLIF page) देता है।

अपने NLog कॉन्फ़िग फ़ाइल पर इस तरह CommandText देखने की तरह होगा:

INSERT INTO [dbo].[log] ([message], [optional]) 
VALUES (@message, NULLIF(@optional, '')) 
+0

+1 मैं 'केस जब ब्ला ब्ला' दृष्टिकोण का उपयोग कर रहा हूं, लेकिन 'न्यूलिफ़' बहुत बेहतर है। धन्यवाद! – Nick

0

मैं एक अलग दृष्टिकोण का उपयोग करें।


क्योंकि मैं प्रश्नों लेखन पसंद नहीं है मैं एक विस्तार है जो मेरे लिए यह करता है बनाया है और मेरी NLog विन्यास की तरह दिखता है: यहाँ दो बातें

<target xsi:type="Database" name="Log" commandText="[dbo].[Log]" dbProvider="System.Data.SqlClient" connectionString=".."> 
    <parameter name="@Timestamp" layout="${longdate:universalTime=true}" /> 
    <parameter name="@LogLevel" layout="${level:uppercase=true}" /> 
    <parameter name="@Logger" layout="${logger}" /> 
    <parameter name="@Message" layout="${message}" /> 
    <parameter name="@Exception:null" layout="${onexception:${exceptionLayout}}" /> 
</target> 

नोटिस:

  • commandText="[dbo].[Log]" जो प्रारूप [Schema].[Table]
  • @Exception:null का पालन करना होगा जहां null मतलब है कि यह व्यर्थ

कोई <commandText> तत्व नहीं है है, लेकिन इसके बजाय मैं इस एक्सटेंशन का उपयोग मापदंडों से स्वचालित रूप से INSERT बनाने के लिए।

public static class NLogExtensions 
{ 
    // The commandText attribute must conatain at least the table name. 
    // Each identifier must be enclosed in square brackets: [schemaName].[tableName]. 

    public static void GenerateDatabaseTargetInsertQueries(this NLog.Config.LoggingConfiguration config) 
    { 
     var tableNameMatcher = new Regex(@"^(\[(?<schemaName>.+?)\].)?\[(?<tableName>.+?)\]$"); 

     var autoCommandTextDatabaseTargets = 
      config.AllTargets 
       .OfType<DatabaseTarget>() 
       .Where(x => tableNameMatcher.IsMatch(x.CommandText())) 
       .Select(x => x); 

     foreach (var databaseTarget in autoCommandTextDatabaseTargets) 
     { 
      databaseTarget.CommandText = databaseTarget.CreateCommandText(); 
     } 
    } 

    internal static string CommandText(this DatabaseTarget databaseTarget) 
    { 
     return ((NLog.Layouts.SimpleLayout)databaseTarget.CommandText).OriginalText; 
    } 

    internal static string CreateCommandText(this DatabaseTarget databaseTarget) 
    { 
     const string insertQueryTemplate = "INSERT INTO {0}({1}) VALUES({2})"; 

     return string.Format(
       insertQueryTemplate, 
       databaseTarget.CommandText(), 
       string.Join(", ", databaseTarget.Parameters.Select(x => x.Name())), 
       string.Join(", ", databaseTarget.Parameters.Select(x => 
       { 
        var sql = 
         x.Nullable() 
         ? string.Format("NULLIF({0}, '')", x.FullName()) 
         : x.FullName(); 

        // Rename the SqlParameter because otherwise SqlCommand will complain about it. 
        x.Name = x.FullName(); 

        return sql; 
       }))); 
    } 
} 

और

public static class NLogDatabaseTarget 
{ 
    public static void GenerateInsertQueries() 
    { 
     NLog.LogManager.Configuration.GenerateDatabaseTargetInsertQueries(); 
    } 
} 

Additionaly यह पैरामीटर नाम पार्स और नल मापदंडों के लिए NULLIF सम्मिलित कर सकते हैं।

एक और विस्तार मुझे इसे पार्स करने के लिए मदद करता है:

public static class DatabaseParameterInfoExtensions 
{ 
    // https://regex101.com/r/wgoA3q/2 

    private static readonly Regex ParamRegex = new Regex("^(?<prefix>.)(?<name>[a-z0-9_\-]+)(?:[:](?<null>null))?", RegexOptions.IgnoreCase); 

    public static string Prefix(this DatabaseParameterInfo parameter) 
    { 
     return ParamRegex.Match(parameter.Name).Groups["prefix"].Value; 
    } 

    public static string Name(this DatabaseParameterInfo parameter) 
    { 
     return ParamRegex.Match(parameter.Name).Groups["name"].Value; 
    } 

    public static string FullName(this DatabaseParameterInfo parameter) 
    { 
     return string.Format("{0}{1}", parameter.Prefix(), parameter.Name()); 
    } 

    public static bool Nullable(this DatabaseParameterInfo parameter) 
    { 
     return ParamRegex.Match(parameter.Name).Groups["null"].Success; 
    } 
} 

इसका मतलब है आप, डेटाबेस लक्षित करने के लिए commandText="[dbo].[Log]" विशेषता जोड़ने क्वेरी निकालें और नल स्तंभों की पैरामीटर नाम करने के लिए :null जोड़ने की जरूरत है।

कोड में आप बस इसे कॉल करें और एक्सटेंशन जादू करेंगे।

NLogDatabaseTarget.GenerateInsertQueries(); 
संबंधित मुद्दे