2013年5月29日 星期三

【SQL】Group by and Top 1


參考:[SQL] 於多筆重複資料中取得該重複群組中最新一筆資料


今天也遇到一個需求是將group by完後的資料挑出最新的一筆
模擬的原始資料大致如下


我希望抓出每個人在在每個地點所做的最後一件事情,寫法如下:
  • 先將每個人跟地點透過時間由大到小歸類
                 select *  ,ROW_NUMBER() over(partition by location,who order by time Desc ) as row_index
                 from timeline
             
  • 然後
             select *
             from (
                  select *  ,ROW_NUMBER() over(partition by location,who order by time Desc ) as row_index
                  from timeline) as tempTable
             where tempTable.row_index = 1
           
  • 結論就是早點回家,否則也只是在公司吃東西而已 XD

2013年5月27日 星期一

SQL NOT EXISTS


參考
MSDN
結論就是,如果單一欄位要篩選掉就用Not IN
select *
from [order]
where 序號 not in 
(
 select 訂單編號 from orderDetail
)
如果多個欄位要同時符合才篩選掉,就用Not Exists
select *
from [order] a
where not exists
(
 select 訂單編號 from orderDetail b 
 where b.訂單編號 = a.序號 and b.購買日期 = (a.民國年+1911) 
)

2013年5月20日 星期一

【JQuery】透過$.fn.Extend自製Alert Function


Google Drive新增修刪除後顯示訊息的方式,是在畫面上方跑出訊息一段時候後自動消失。
今天就來實作一下這個功能~

首先請先去下載bootstrap,這裡面有個alert的class個人覺得滿漂亮的,所以就拿這個來改吧!!



  • 首先正確的載入bootstrap的CSS跟JavaScript
  • 寫一個自製的JavaScript
    /// <reference path="../jquery-1.9.1.min.js" />
    
    $.fn.extend({
        alert: function (msg) {
            var parentElement = $(this);
            var alertElement = $('<div class="alert">'+
                                    '<button type="button" class="close" data-dismiss="alert">&times;</button>'+
                                    '<span class="text-center">' + msg + '</span>' +
                                '</div>');
    
            //先加到容器內才能算長度
            alertElement.appendTo(parentElement);
    
            //alert區塊的寬度
            var alertWidth = alertElement.width();
            //容器的寬度
            var targetWidth = parentElement.width();
            var position = parentElement.position();
            var _left = position.left + (targetWidth / 2) - (alertWidth / 2);
    
            alertElement.css({ top: position.top, left: _left }).fadeIn(500);
    
            //時間到就清除掉
            var timer = setTimeout(function () { alertElement.fadeOut(); clearTimeout(timer); }, 5000);
        }
    });
    

    其中$.fn.extend是JQuery的擴充function
  • 改一些bootstrap的CSS,通常我會將這段另外寫在自己的css檔案裡面,盡量避免直接改動官方的任何檔案
    /* alert訊息 */
    .alert
    {   
        width:300px;
        z-index:3;
        display:none;
        color:#0300FA;
        position:absolute;
        margin:0px;
    }
    
    .alert>span
    {
        display:inline-block;
        width:270px;
        word-break:break-all;
    }
    
  • 之後呼叫這樣寫
    //在這邊$('#BackStageBody')為要出現訊息方塊的區域,剛剛擴充的function會自動計算其寬高,並把訊息顯示在正確的位置
    $('#BackStageBody').alert('新增成功')
    
  • 效果如下

2013年5月19日 星期日

【SharePoint 2013】開啟BreadCrumb


  • 用Sharepoint Designer登入SharePoint網站
  • 編輯主板頁面
  • 找到GlobalBreadCrumbNavPopout
  • 做以下修改
    • 將div class="ms-breadcrumb-dropdownBox"旁邊的display:none修改掉
    • 將GlobalBreadCrumbNavPopout的Visible改為True
    • <div class="ms-breadcrumb-dropdownBox" style="display:inline;">
      <SharePoint:AjaxDelta id="DeltaBreadcrumbDropdown" runat="server">
       <SharePoint:PopoutMenu
        Visible="true"
        runat="server"
        ID="GlobalBreadCrumbNavPopout"
        IconUrl="/_layouts/15/images/spcommon.png?rev=23"
        IconAlt="<%$Resources:wss,master_breadcrumbIconAlt%>"
        ThemeKey="v15breadcrumb"
        IconOffsetX="215"
        IconOffsetY="120"
        IconWidth="16"
        IconHeight="16"
        AnchorCss="ms-breadcrumb-anchor"
        AnchorOpenCss="ms-breadcrumb-anchor-open"
        MenuCss="ms-breadcrumb-menu ms-noList">
      
  • breadCrumb就出現了

2013年5月14日 星期二

2013年5月8日 星期三

【MVC】擴充HtmlHelper


  • 第一個範例,讓ActionLink可以放HTML標籤進去
  • 首先我先在專案中建立一個資料夾,並且在裡面新增一個類別檔案
  • //將命名空間改成System.Web.Mvc.Html,使用前不用修改~/Views/Web.config
    namespace System.Web.Mvc.Html
    {
        public static class MyHtmlHelperExtensions
        {
            public static MvcHtmlString InsertHtmlTagActionLink(this AjaxHelper ajaxHelper,string linkText ,string actionName, string controllerName, AjaxOptions ajaxOptions) 
            {
                var lnk = ajaxHelper.ActionLink("[replaceme]", actionName, controllerName, ajaxOptions);
                return MvcHtmlString.Create(lnk.ToString().Replace("[replaceme]", linkText));
            }
        }
          
  • 使用方式如下
    @Ajax.InsertHtmlTagActionLink("<i class='icon-file'></i>"+@childFunction.funname, action, controller, new AjaxOptions { UpdateTargetId="BackStageBody" });
         
  • 第二個範例,將TextBoxFor固定塞入一個data-content的html屬性,並將值給這個屬性
  • public static MvcHtmlString TextBoxFor_WithOriginData<TModel, TProp>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProp>> expression,object HtmlAttributes = null) 
    {
        //透過AnonymousObjectToHtmlAttributes將HtmlAttribute讀取出來
        var attrs = HtmlHelper.AnonymousObjectToHtmlAttributes(HtmlAttributes);
        //將expression的值抓出來放到data-content這個屬性中
        attrs.Add("data-content",ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData).Model);
        var txtBoxFor = htmlHelper.TextBoxFor(expression, attrs);
        return MvcHtmlString.Create(txtBoxFor.ToString());
    }
       
  • 第三個範例,加入Img這個Tag
  • public static MvcHtmlString ImageFor_WithOriginData<TModel, TProp>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProp>> expression, object HtmlAttributes = null) 
    {
        string value = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData).Model == null ? "" : ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData).Model.ToString();
        //屬性的值
        string propname = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData).PropertyName;
    
        //透過AnonymousObjectToHtmlAttributes將HtmlAttribute讀取出來
        var attrs = HtmlHelper.AnonymousObjectToHtmlAttributes(HtmlAttributes);
        attrs.Add("data-content", value);
        attrs.Add("src", value);
        attrs.Add("name", propname);
    
        var img = new TagBuilder("img");
        img.MergeAttributes(attrs);
               
        return MvcHtmlString.Create(img.ToString(TagRenderMode.SelfClosing));
    }
    

2013年5月7日 星期二

【MVC】回傳Json格式,並用JQuery解讀


View中回傳Json格式的物件
var jsonObject = JsonConvert.SerializeObject(Repository.GetExhibitionList().OrderBy(o => o.CreateDate).ToArray());
return Json(jsonObject);

JQuery中解讀
var List = $.parseJSON(returnvalue);

var tr = [];
//轉換日期格式
$.each(List, function (index, val) {
           
    tr.push('<tr class="exhibitionItem">' +
            '<td>' + (index + 1) + '</td>' +
            '<td>' + val.ExhibitionName + '</td>' +
            '<td>' + val.CreateDate + '</td>' +
            '<td>' + val.EditDate + '</td>' +
           '</tr>');
});

動態新增或刪除MenuTab與MultiView


雖然我應該八萬年都不會用這兩個控制項,但今天幫人家改了一個莫名其妙的問題,就順便紀錄一下吧
必須寫在Page_Init,且MultiView在新增時不能放在Page_Load裡面,不然有時候會當掉....超怪!!
 Protected Sub Page_Init(ByVal Sender As Object, ByVal e As EventArgs) Handles Me.Init

        If Not Page.IsPostBack Then
            Me.MultiViewControl.Controls.Clear()
            Select Case Request.QueryString("Type")
                Case "01"
                    Me.MenuTab.Items.RemoveAt(0)
                    Me.MenuTab.Items.RemoveAt(0)
                    Me.MenuTab.Items.RemoveAt(0)
                    Me.MenuTab.Items(0).Selected = True
                    
                    Me.MultiViewControl.Controls.Add(View4)
                Case "02"
                    Me.MenuTab.Items.RemoveAt(0)
                    Me.MenuTab.Items.RemoveAt(1)
                    Me.MenuTab.Items.RemoveAt(1)
                    Me.MenuTab.Items(0).Selected = True

                    Me.MultiViewControl.Controls.Add(View2)
                Case Else
                    Me.MenuTab.Items.RemoveAt(3)
                    
                    Me.MultiViewControl.Controls.Add(View1)
                    Me.MultiViewControl.Controls.Add(View2)
                    Me.MultiViewControl.Controls.Add(View3)
            End Select
        End If
    End Sub



補充!!!
  • 之前是用QueryString的參數來決定要加入哪些View,但因為其實開的WebForm都是同一個,所以如果有使用一些控制項(例如:UpdatePanel之類的),會回傳ViewState不一致或一些奇奇怪怪的問題一堆,所以改正了上述的作法,MultiView從頭到尾都不移除,而是依據目前Menu選取來決定show哪個View
  • 修正版本
     Protected Sub Page_Init(ByVal Sender As Object, ByVal e As EventArgs) Handles Me.Init
    
            If Not Page.IsPostBack Then
                Select Case Request.QueryString("Type")
                    Case "01"
                        Me.MenuTab.Items.RemoveAt(0)
                        Me.MenuTab.Items.RemoveAt(0)
                        Me.MenuTab.Items.RemoveAt(0)
                        Me.MenuTab.Items(0).Selected = True
                        
                    Case "02"
                        Me.MenuTab.Items.RemoveAt(0)
                        Me.MenuTab.Items.RemoveAt(1)
                        Me.MenuTab.Items.RemoveAt(1)
                        Me.MenuTab.Items(0).Selected = True
    
                    Case Else
                        Me.MenuTab.Items.RemoveAt(3)
                        
                End Select
            End If
     End Sub
     Protected Sub View_Select(sender As Object, e As EventArgs) Handles Menu1.PreRender
            Select Case Menu1.SelectedValue
                Case "1"
                    MultiView1.ActiveViewIndex = 0
                Case "2"
                    MultiView1.ActiveViewIndex = 1
                Case "3"
                    MultiView1.ActiveViewIndex = 2
            End Select
     End Sub
    
    

2013年5月2日 星期四

跨DB select


select * from opendatasource('SQLNCLI10','Data Source=192.168.1.110;User ID=帳號;Password=密碼').DataBaseName.dbo.TableName

2013年5月1日 星期三

【C#】透過C#加密


strKey與strIV是用來加密的參數,可以替換任何字元但一定要8個字
 //加密動作
private static string strKey = "toyo1234";  
private static string strIV = "lovecode";

/// <summary>字串編碼</summary>
/// <param name="strSource">原始字串</param>
/// <returns>編碼後的結果字串</returns>
public static string enCrypt(string strSource)
{
   MemoryStream ms = new MemoryStream();
   DESCryptoServiceProvider key = new DESCryptoServiceProvider();  
   CryptoStream encStream = new CryptoStream(ms, key.CreateEncryptor(Encoding.Default.GetBytes(strKey),     Encoding.Default.GetBytes(strIV)), CryptoStreamMode.Write);
   StreamWriter sw = new StreamWriter(encStream);
   sw.WriteLine(strSource);
   sw.Close();
   encStream.Close();
   byte[] buffer = ms.ToArray();         
   ms.Close();
   return Convert.ToBase64String(buffer);   
}


/// <summary>字串解碼</summary>
/// <param name="strSource">加密過的字串</param>
/// <returns>解碼後的結果字串</returns>
public static string deCrypt(string strSource)
{
    MemoryStream ms = new MemoryStream(Convert.FromBase64String(strSource));
    DESCryptoServiceProvider key = new DESCryptoServiceProvider();
    CryptoStream encStream = new CryptoStream(ms, key.CreateDecryptor(Encoding.Default.GetBytes(strKey), Encoding.Default.GetBytes(strIV)), CryptoStreamMode.Read);
    StreamReader sr = new StreamReader(encStream);
    string val = sr.ReadLine();
    sr.Close();
    encStream.Close();
    ms.Close();

    return val;
}

Entity Framework問題筆記


目前使用的是MVC4 + Entity Framework

Q:無法更新 EntitySet 'xxxx',因為它有 DefiningQuery,但是在 項目中沒有 項目來支援目前的作業。
A:這是因為 Table 沒有 PK 的關係,所以 EF 就認定這是唯讀的 Table ,在 EDMX 的 Model 中的 Table 的欄位,加上 pk 後就正常了



Q:在設計資料庫時明明有指定欄位的預設值,可是每次透過 EF 新增資料時,該欄位的值卻是 null?
A:這是因為 DB 該欄位有 Default Value 而且又不允許 null,在 Visual Studio 中開啟 .edmx 檔案,在模型編輯器中點選 entity 的屬性,然後到屬性視窗中設定其 Default Value 屬性。參考下圖:


參考自:
Entity Framework 4 的錯誤訊息排除
Entity Framework 欄位預設值相關問題