0%

  • 一樣參考保哥的解決 LINQ to SQL 資料庫更新衝突的情形與公司前輩的Source Code

  • 發生原因:有可能我們在跟DB取得某個欄位時得到A這個值,但當我們改動這個值並嘗試更新回DB時,可能DB早就被其他使用者改成B了。DBContext SubmitChanges會去比對這個欄位最初值是否與DB目前的值一致避免Dirty Data的問題,但當上述情況發生時則會擲出Exception。各種處理方式如下:```csharp
    try
    {
    _dbContext.SubmitChanges(System.Data.Linq.ConflictMode.ContinueOnConflict);
    }
    catch (System.Data.Linq.ChangeConflictException ex)
    {
    foreach (System.Data.Linq.ObjectChangeConflict occ in _dbContext.ChangeConflicts)
    {

    // 採用資料庫的查詢出來的值,目前物件的值將會被資料庫最新查到的複寫
    //occ.Resolve(System.Data.Linq.RefreshMode.OverwriteCurrentValues);
    
        // 採用目前物件中的值,並更新資料庫中的版本
    //occ.Resolve(System.Data.Linq.RefreshMode.KeepCurrentValues);
    
        // 僅更新此物件中變更的欄位,僅將變更的欄位寫入資料庫(或稱為合併更新)
    occ.Resolve(System.Data.Linq.RefreshMode.KeepChanges);
    

    }
    // 注意:解決完衝突之後要記得重新再 SubmitChanges() 一次,否則一樣不會更新資料庫
    _dbContext.SubmitChanges();
    }


  • 這個東西做了八百萬遍了還是常常忘記在哪設定,所以決定寫起來方必查詢(汗)* 首先,SQL Server上右鍵 > 屬性 > 安全性 > 選擇SQL Server及Windows驗證模式

  • 安全性 > 登入 > SA帳戶 > 屬性

    狀態 > 登入 > 啟用
  • 重新啟動SQL服務

研究了老半天終於搞懂了,來做一下簡單的筆記
從.NET 2.0開始就已經開始實行的Form驗證模式,今天拜讀了保哥的「概略解釋 Forms Authentication 的運作」後測試的簡單心得

使用這個方法即表示驗證成功,這個驗證會記錄在電腦的cookie當中

1
FormsAuthentication.RedirectFromLoginPage(strUsername, false);

但如果你想要關閉瀏覽器時就登出,你就得改用以下方式將cookie記錄在web browser當中

1
2
3
4
5
6
7
8
//改發Ticket的方式
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, username, DateTime.Now, DateTime.Now.AddMinutes(30),false, userdata, FormsAuthentication.FormsCookiePath);

// Encrypt the ticket.
string encTicket = FormsAuthentication.Encrypt(ticket);

// Create the cookie.
Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encTicket));

那如果又要實作,記住我xx天不用重新登入的功能呢?

1
2
3
4
5
6
7
8
9
//除了剛剛發Ticket之外
if (bool.Parse(remember))
{
//如果打勾記住我的話
HttpCookie cookie = new HttpCookie("rememberme");
cookie.Value = SysHelper.enCrypt(account);
cookie.Expires = DateTime.Now.AddDays(3);
Response.Cookies.Add(cookie);
}

這樣下次登入的時候只要判斷這個cookie存不存在就可以放行了!!

1
2
3
4
5
6
7
8
9
10
11
12
13
//登入Login頁面時,先判斷Form驗證已經通過了嗎?
if (!User.Identity.IsAuthenticated)
{
//沒通過的話,判斷cookie存不存在。有的話表示此人上次登入時有勾記住我!!
if ( Request.Cookies["backend"] != null)
{
//cookie如果過期的話會判斷為null,所以進得來表示cookie還沒過期,可以發Ticket給他
passTicket(SysHelper.deCrypt(Request.Cookies["rememberme"].Value), "");

return Redirect("/backend");
}
return View();
}

登出

1
2
3
4
5
6
7
8
9
10
11
//呼叫這個方法就已經登出摟~
FormsAuthentication.SignOut();

if (Request.Cookies["backend"] != null)
{
//如果cookie還沒過期,既然已經登出當然要把它重新設定為過期啦!!
HttpCookie myCookie = new HttpCookie("backend");
myCookie.Expires = DateTime.Now.AddDays(-1d);
Response.Cookies.Add(myCookie);
}
return Redirect("/backend");

最後不要搞混Response與Request了。我寫的時候沒注意到害我Debug超久的….(汗)

  • 如果在呼叫PartialView時用以下傳值方式 ```csharp
    //透過第三個參數用ViewDataDictionary的方式傳遞參數,會導致之前存的ViewBag的值在PartialView裡面變成Null讀不到
    @Html.Partial(“_at_article_endlink”, linklist,new ViewDataDictionary { { “linktitle”, Model.LINKTITLE } })
1
2
3
4
5

* 最後改良的方式變成在外面先存成ViewBag的值,接下來PartialView裡面就一切正常了 ```csharp
@{ViewBag.linktitle = na.LINKTITLE;}
@Html.Partial("_at_article_endlink", linklist)

1
2
3
4
5
6
7
8
9
10
11
$('input[type="file"]').on('change', function () {
var file = $(this).val();
if (!file.match(/^([0-9a-zA-Z_\-~ :\\])+(.jpg|.JPG|.jpeg|.JPEG|.bmp|.BMP|.gif|.GIF|.png|.PNG)$/))
{
alert('只允許上傳圖檔');
var control = $(this);
//如果上傳的檔案格式不符合,將該Control換成新的
control.replaceWith(control = control.clone(true));
}
});

  • Function如下 ```vb
    ‘’’
    ‘’’’’’

    ‘’’ 要新增空白行的GridView
    ‘’’ 要加入幾行
    ‘’’
    Public Shared Sub GridView_AddEmptyRow(gv As GridView, count As Integer)
    Dim dt As DataTable = New DataTable()
    Dim dr As DataRow
    For i = 0 To gv.Columns.Count - 1 Step 1
      dt.Columns.Add(New DataColumn(gv.Columns(i).HeaderText, System.Type.GetType("System.String")))
    
    Next
    For i = 1 To count Step 1
      dr = dt.NewRow()
      For x = 0 To gv.Columns.Count - 1 Step 1
          dr(gv.Columns(x).HeaderText) = String.Empty
      Next
      dt.Rows.Add(dr)
    
    Next
    gv.DataSource = dt
    gv.DataBind()
    End Sub

因為某些搜尋條件的不同,造成要顯示的欄位可能也略有差異,一般可以透過多個GridView隱藏來隱藏去的方法,或是動態將某些Column隱藏起來,今天試的方法是在搜尋完後DataBind之前先將GridView的欄位換成自己想要的,新增一般BoundField沒什麼太特別的,但TemplateField就卡關了….參考很多資料後來做個筆記!!!

  • 先將該準備的類別與方法準備好
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    ''' <summary>
    ''' 複製控制項
    ''' </summary>
    ''' <param name="taget"></param>
    ''' <param name="source"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function Clone(ByVal taget As Object, ByVal source As Object) As Object
    For Each p As System.Reflection.PropertyInfo In source.GetType().GetProperties()
    If p.CanRead AndAlso p.CanWrite Then
    p.SetValue(taget, p.GetValue(source, p.GetIndexParameters()), p.GetIndexParameters())
    End If
    Next
    Return taget
    End Function

    '新增一個類別實作ITemplate介面,就會跑出InstantiateIn的方法
    Public Class gvTemplate
    Implements ITemplate

    Private Property templateType As DataControlRowType
    Private Property columnName As String
    Private Property Control As Object
    Public Sub New(type As DataControlRowType, colname As String, ctrl As Object)
    templateType = type
    columnName = colname
    Control = ctrl
    End Sub

    Public Sub InstantiateIn(container As Control) Implements ITemplate.InstantiateIn
    Select Case templateType
    Case DataControlRowType.Header
    If Control Is Nothing Then
    '如果沒有沒有控制項,則塞入粗體字
    Dim lt As Literal = New Literal()
    lt.Text = "<B>" + columnName + "</B>"
    container.Controls.Add(lt)
    ElseIf TypeOf Control Is CheckBox Then
    '否則塞入控制項
    container.Controls.Add(Control)
    End If
    Case DataControlRowType.DataRow
    Dim obj As Object
    If Not Control Is Nothing Then
    Select Case Control.GetType().Name
    Case "CheckBox"
    obj = New CheckBox()

    '如果有傳入WebControl的話,複製一個新的並把它加到DataRow中
    '如果沒這麼做就直接將傳入的Control加入Container當中
    '會變成只有最後一行有那個Control(Control為Reference型別)
    SysHelper.Clone(obj, Control)
    End Select
    obj = SysHelper.Clone(obj, Control)
    Else
    obj = New Label()
    AddHandler CType(obj, Label).DataBinding, AddressOf data_DataBinding
    End If
    container.Controls.Add(obj)
    End Select
    End Sub

    Private Sub data_DataBinding(sender As Object, e As EventArgs)
    Dim lbl As Label = CType(sender, Label)
    Dim row As GridViewRow = CType(lbl.NamingContainer, GridViewRow)
    lbl.Text = DataBinder.Eval(row.DataItem, columnName).ToString()
    End Sub
    End Class
  • 使用方法如下
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    Private Sub setGridViewColumns(ByVal mode As GriviewMode)
    gvSummons.Columns.Clear()
    '新增TemplateField的方法
    Dim TemplateField As TemplateField = New TemplateField()
    TemplateField.ItemStyle.HorizontalAlign = HorizontalAlign.Center
    Dim cb As CheckBox = New CheckBox()
    cb.ID = "cbSelectAll"
    cb.Text = "註記"
    cb.CssClass = "gvSummonsSelectAll"
    TemplateField.HeaderTemplate = New SysHelper.gvTemplate(DataControlRowType.Header, "", cb)

    cb = New CheckBox()
    cb.ID = "cbSelect"
    cb.CssClass = "gvSummonsSelect"
    TemplateField.ItemTemplate = New SysHelper.gvTemplate(DataControlRowType.DataRow, "", cb)
    gvSummons.Columns.Add(TemplateField)


    '新增BoundField的方法
    Dim BoundField As BoundField = New BoundField()
    BoundField.DataField = "voucherno"
    BoundField.HeaderText = "傳票號碼"
    BoundField.ItemStyle.HorizontalAlign = HorizontalAlign.Center
    gvSummons.Columns.Add(BoundField)
    End Sub

JQuery Sortable套件

這個常常被我用來設定排序的套件,但有個缺點就是它在拉動時父容器不會跟著滾動ScrollBar,所以自己稍做修改了一下(包含上下按鈕的功能)

  • 先看一下成果
  • HTML ```html
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

* CSS ```css
#sortable { list-style-type: none; margin: 0; padding: 0; width: 150px; }
#sortable li { margin: 0 5px 5px 5px; padding: 5px; font-size: 1.2em; height: 1.5em; }
html>body #sortable li { height: 1.5em; line-height: 1.2em; }
.ui-state-highlight { height: 1.5em; line-height: 1.2em; }

#sortable
{
border:1px dotted gray;
overflow:auto;
height:500px;
display:inline-block;
width:130px;
}
#sortbtn
{
display:inline-block;
width:30px;
vertical-align:top;
position:relative;
top:180px;
}

  • JavaScript ```javascript
    $(function () {
    var is_dragging = false;
    $(‘#sortable’).disableSelection().sortable({

      placeholder: "ui-state-highlight",
      axis: 'y',
      start: function (event, ui) { is_dragging = true; itemSelect(ui.item); },
      stop: function (event, ui) { is_dragging = false;}
    

    }).mousemove(function (e) {

      if (is_dragging) {
          $('#sortable').scrollTop(function (i, v) {
              var h = $('#sortable').height();
              var y = e.clientY - h / 2;
              return v + y * 0.05;
          });
      }
    

    });

      //=== 點擊Item時
    

    $(‘#sortable > li’).click(function (event) {

      itemSelect(this);
    

    });

      ////=== 上下按鈕
    

    $(‘#btnUp,#btnDown’).click(function () {

      var Container_height = $('#sortable').height();
      var position_top = $('#sortable').position().top;
    
          if (lastSelect != null) {
          if ($(this).prop('id') == "btnUp") {
              lastSelect.prev().before(lastSelect);
              //卷軸向上滾動
              $('#sortable').scrollTop(function (i, v) {
                  if (lastSelect.position().top <= position_top + Container_height / 2) {
                      return v - lastSelect.height();
                  }
              });
          }
          else {
              lastSelect.next().after(lastSelect);
              //卷軸向下滾動
              $('#sortable').scrollTop(function (i, v) {
                  if (lastSelect.position().top >= position_top + Container_height / 2) {
                      return v + lastSelect.height();
                  }
              });
          }
      }
    

    });
    });


參考

今天網址列傳遞參數時,透過Request.QueryString轉回來時變成亂碼。參考該部落格的解法後做個小筆記避免自己忘記

  • 如果是用JavaScript串網址的話,用encodeURI()這個方法 ```javascript
    var Feature = ‘dialogWidth:500px;dialogHeight:200px;status:0;help:0;’;
    var Url = ‘wFrmAccount_Insert.aspx?src=’ + src + ‘&bancode=’ + bancode + ‘&ym=’ + ym + ‘&type=’ + type;
    //將網址先編譯過後再傳遞
    window.showModalDialog(encodeURI(Url), window, Feature
1
2
3
4

* 如果是在ServerSide串網址,則用以下方法 ```csharp
Response.Redirect("WebForm2.aspx?id=" + Server.UrlEncode("中文"))

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

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

我希望抓出每個人在在每個地點所做的最後一件事情,寫法如下:

  • 先將每個人跟地點透過時間由大到小歸類 ```sql
    select * ,ROW_NUMBER() over(partition by location,who order by time Desc ) as row_index
           from timeline
    
1
2
3
4
5
6
7
         [![](http://3.bp.blogspot.com/-hbcc3sD90ek/UaXGjjKL0UI/AAAAAAAADmw/jh2ks4iABqM/s1600/%E6%9C%AA%E5%91%BD%E5%90%8D.png)](http://3.bp.blogspot.com/-hbcc3sD90ek/UaXGjjKL0UI/AAAAAAAADmw/jh2ks4iABqM/s1600/%E6%9C%AA%E5%91%BD%E5%90%8D.png)*   然後        ```sql
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

   [![](http://4.bp.blogspot.com/-E-Syl1jp57A/UaXHnZ_4jwI/AAAAAAAADm8/4cLCGkPmMag/s1600/%E6%9C%AA%E5%91%BD%E5%90%8D.png)](http://4.bp.blogspot.com/-E-Syl1jp57A/UaXHnZ_4jwI/AAAAAAAADm8/4cLCGkPmMag/s1600/%E6%9C%AA%E5%91%BD%E5%90%8D.png)*   結論就是早點回家,否則也只是在公司吃東西而已 XD