2015年5月31日 星期日

Log4Net採用現在資料庫的方法

延用上一篇Log4Net記錄log除錯方式(MS-SQL)在Log4Net Appender的資料庫連線字串,會有自己的資料庫連線字串

但是若本身就有有原有的資料庫時,這時要改變資料庫,則設要調整兩個連線字串的地方,那是否會有辦法可以讓Log4Net去捉取我原有的連線字串呢?辦法還是有的

若我本身的資料庫連線字串為

<connectionstrings>
       <add connectionstring="Data Source=127.0.0.1;Initial Catalog=[DataBaseName];User ID=[UserID];Password=[PassWord];Persist Security Info=True;Timeout=2" name="Connection1">
</add></connectionstrings>


而原有的Log4Net的連線方式,只需要新增一個connectionStringName,然後把connectionString拿掉


<appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
      <buffersize value="1">
      <connectiontype value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <!--調整的地方-->
      <connectionstringname value="Connection1">

      <!--拿掉的地方-->
      <!--<connectionstring value="data source=127.0.0.1;initial catalog=[DataBaseName];integrated security=false;persist security info=True;User ID=[UserID];Password=[PassWord] />-->

</connectionstringname></connectiontype></buffersize></appender> 



2015年5月21日 星期四

Log4Net記錄log除錯方式(MS-SQL)

Log4Net的前身原本Java的Log4J,此為簡易的記錄日誌管理器
套用的方式有幾個步驟需要說明
1、調整AssemblyInfo.cs檔
新增以下一行

[assembly: log4net.Config.DOMConfigurator()]

2、建立資料庫

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
)
3、在App.config或web.config上加上下列字段
加在

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

    <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
      <file value="LogFiles/"> <!--存放log檔案的路徑-->
      <staticlogfilename value="false">
      <appendtofile value="true">
      <rollingstyle value="Date">
      <datepattern value="yyyyMMdd.lo\g"> <!--log檔案的命名-->
      <layout type="log4net.Layout.PatternLayout">
        <conversionpattern value="%-5p %date{yyyy/MM/dd HH:mm:ss} %-20c{1} %-20M %m%n">
      </conversionpattern></layout>
    </datepattern></rollingstyle></appendtofile></staticlogfilename></file></appender>

    <appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
      <buffersize value="2">
      <connectiontype value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <connectionstring value="data source=[Your IP Address];initial catalog=[DataBaseName];integrated security=false;persist security info=True;User ID=[login name];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">
      </layout></dbtype></parametername></parameter>
      <parameter>
        <parametername value="@thread">
        <dbtype value="String">
        <size value="255">
        <layout type="log4net.Layout.PatternLayout">
          <conversionpattern value="%thread">
        </conversionpattern></layout>
      </size></dbtype></parametername></parameter>
      <parameter>
        <parametername value="@log_level">
        <dbtype value="String">
        <size value="50">
        <layout type="log4net.Layout.PatternLayout">
          <conversionpattern value="%level">
        </conversionpattern></layout>
      </size></dbtype></parametername></parameter>
      <parameter>
        <parametername value="@logger">
        <dbtype value="String">
        <size value="255">
        <layout type="log4net.Layout.PatternLayout">
          <conversionpattern value="%logger">
        </conversionpattern></layout>
      </size></dbtype></parametername></parameter>
      <parameter>
        <parametername value="@message">
        <dbtype value="String">
        <size value="4000">
        <layout type="log4net.Layout.PatternLayout">
          <conversionpattern value="%message">
        </conversionpattern></layout>
      </size></dbtype></parametername></parameter>
      <parameter>
        <parametername value="@exception">
        <dbtype value="String">
        <size value="2000">
        <layout type="log4net.Layout.ExceptionLayout">
      </layout></size></dbtype></parametername></parameter>
    </commandtext></connectionstring></connectiontype></buffersize></appender>
    
    <root>
      <level value="ALL">
      <appender-ref ref="AdoNetAppender">
    </appender-ref></level></root>


    <logger name="WebForm1">

      <level value="INFO">

      <appender-ref ref="RollingFileAppender">

    </appender-ref></level></logger>

  </log4net>  

在此用了2種appender,一個是直接記錄在文字檔內,即為name=RollingFileAppender的appender,另一個為將log記錄在SQL Server上,即為AdoNetAppender的appender。

而xml裡的<root></root>即為系統內預設的LogManager,若要使用別的LogManager,則用 <logger name=""></logger>的方式,使用方式在下面進行說明。
4、 在cs部步,則加上下面部份

    public partial class LoginPage
    {
        //使用LogManager預設的Log, 記錄Log在資料庫內
        public static readonly ILog TxtLog1 = LogManager.GetLogger(typeof(LoginPage));
        //使用Log Name為WebForm1的Log,記錄Log在文字檔內
        public static readonly ILog TxtLog2 = LogManager.GetLogger("WebForm1");
        protected void Page_Load(object sender, EventArgs e)
        {
            TxtLog1.Info("DB Log:Start");
            TxtLog2.Warn("File Log:Start");        
        }
    }

這樣即可進行Log記錄

2015年5月18日 星期一

TreeView與資料階層關係

一般TreeView的節點功能,來做資料庫階層關係設計,這時我們可以利用ADO.Net上的DataRelations,來建立資料表上的關係性
1、資料庫欄位:
MyPK:當筆資料的Key值
ParentID:父節點的Key值,若為NULL則為最上層

 2、程式部分
可用DataRelation來建立表的關連性
注意:1、表上的所有資料都需要對映到,不可有ParentID=5,但在父節點到找不到ID=5的情況
           2、ParentID為Null是允許的,代表為最上層,但ParentID若設定為""空白的話,程式上會判定還有一個父節點ID="",此時程產在查尋關聯時會產生錯誤
設定資料
        
        public Void SetData()
        {  
            //捉取資料到DataTable
            DataTable dt = qo.DoQueryToTable();
            //將關聯Table加入到DataSet以供建立關係,因目前資料關係性是在自己本表上,所以只需Add一次
            DataSet ds = new DataSet();
            ds.Tables.Add(dt);
            //產生關聯性
            ds.Relations.Add("NodeRelation", ds.Tables[0].Columns["MyPK"], ds.Tables[0].Columns["ParentID"]);
            
            foreach (DataRow dr in dt.Rows)
            {
                if(dr.IsNull("ParentID"))
                {
                    TreeNode rootNode = this.TreeView1.FindNode("WBS");
                    string strText = dr["Tag"].ToString() + " : " + dr["Memo"].ToString();                    
                    
                    TreeNode addNode = CreateNode(strText, dr["MyPK"].ToString(), true);
                    rootNode.ChildNodes.Add(addNode);
                    //搜尋子節點,並進行遞迴
                    PopulateSubTree(dr, addNode);
                }
            }
        }
建立節點
        
        private TreeNode CreateNode(string text, string id, bool expanded)
        {
            TreeNode node = new TreeNode(); 
            node.Text = text;
            node.Value = id;
            node.Expanded = true;
            return node;
        }
子節點遞迴搜尋

        
        private void PopulateSubTree(DataRow dbRow, TreeNode node)
        {
            //因有在SetData()上建立資料表上MyPK與ParentID的關連性,所以在這可用GetChildRows捉取子節點
            foreach (DataRow childRow in dbRow.GetChildRows("NodeRelation"))
            {
                string strText = childRow["Tag"].ToString() + " : " + childRow["Memo"].ToString();
                
                TreeNode childNode = CreateNode(strText, childRow["MyPK"].ToString(), true);
                node.ChildNodes.Add(childNode);
                PopulateSubTree(childRow, childNode);
            }
        }

3、最後出現的畫面如下
 而畫面上為何會有像Project一樣的表格呢?這是利用CSS來進行調整的,若去看TreeView的原始碼,可以看出他是由Table組成的,而上面的畫面,則是在TD上調整border即可

td {
    padding: 1px;
    border: 1px solid #D6DDE6;
    text-align: left;
    background-color: #FFF;
    color: #333;
    margin: 1px;
}
參考資料:
MSDN:加入 DataRelations 

動態TreeView 結合資料庫產生節點



2015年5月15日 星期五

Spinner調整字型大小

在Spinner上,並無法直接設定TextSize大小,所以則可以透過一個小技巧去設定TextSize大小

1、設定一個xml檔(spinner_style.xml)

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/spnStyle"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" 
    style="?android:attr/spinnerDropDownItemStyle"
    android:textSize="25sp">
</TextView>
其中android:textSize即可設定fnot size

2、若Spinner數據來源為XML

ArrayAdapter typeAdapter1 = ArrayAdapter.createFromResource(this, 
            R.array.sex_list, R.layout.spinner_style); 
typeAdapter1.setDropDownViewResource(R.layout.spinner_style);
this.spnSex.setAdapter(typeAdapter1);
也可以偷懶直接從Spinner上getAdapter再進行轉型而去設定ViewResource來源

ArrayAdapter typeAdapter2 = (ArrayAdapter)this.spnSex.getAdapter();//直接轉型成ArrayAdapter
typeAdapter2.setDropDownViewResource(R.layout.spinner_style);//將Resource指向自定的Spinner Style
this.spnSex.setAdapter(typeAdapter2);


3、數據來源若是動態產生時,則用以下方式

private static final String[] sex_group={"男","女"};
ArrayAdapter adapter = new ArrayAdapter(this,R.spinner_style.myspinner,sex_group);
this.spnSex.setAdapter(adapter);

Spinner獲取資料方式(XML)

Spinner設定

<Spinner
        android:id="@+id/spnSex"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:entries="@array/sex_list"
        android:prompt="@string/spn_sex_list_prompt" /> 

strings.xml設定

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="sex_list">
        <item >男</item>
        <item >女</item>
    </string-array>
        <string name="spn_sex_list_prompt">請選擇性別</string>
</resources> 
在Spinner上
1、entries直接選取@array/sex_list,則會將array上的item帶入下拉式選單的選則項
2、prompt是設定在未選取資料時,顯示在Spinner上的提示文字

blogger顯示code block方法

1、在設計頁面上,選取範本→自訂

2、進階→新增CSS,將以下文字填寫即可


code {
background-color: #F9F9F9;
border: 1px dashed #2F6FAB;
color: black;
/* line-height: 1.1em; 
padding: 1em;*/
}

pre code {
display: block; /* fixes a strange ie margin bug */
font-family: Courier New;
font-size: 10pt;
overflow:auto;
background: #f0f0f0 url(data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAASwCAYAAAAt7rCDAAAABHNCSVQICAgIfAhkiAAAAQJJREFUeJzt0kEKhDAMBdA4zFmbM+W0upqFOhXrDILwsimFR5pfMrXW5jhZr7PwRlxVX8//jNHrGhExjXzdu9c5IiIz+7iqVmB7Hwp4OMa2nhhwN/PRGEMBh3Zjt6KfpzPztxW9MSAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzB8HS+J9kUTvzEDMwAAAABJRU5ErkJggg==) left top repeat-y;
border: 1px solid #ccc;
padding: 10px 10px 10px 21px;
max-height:1000px;
line-height: 1.2em;
}


日後要將程式碼顯示於BLOG時,只需將程式碼的前後加上<pre><code class="prettyprint">與</code></pre>即可


 private String getHelloWorld()
 {
  return "Hello World";
 }