說明
進行DB schema更新時使用database project的結構描述比較
但按下比較時狀態列出現目標無法使用的錯誤訊息
重開vs2017也沒用
解法
參考這裡
https://stackoverflow.com/questions/37463279/sql-schema-comparison-error-target-is-unavailable
將連線字串的帳號名稱格式改為加上伺服器名稱
username@servername
就成功了
進行DB schema更新時使用database project的結構描述比較
但按下比較時狀態列出現目標無法使用的錯誤訊息
重開vs2017也沒用
參考這裡
https://stackoverflow.com/questions/37463279/sql-schema-comparison-error-target-is-unavailable
將連線字串的帳號名稱格式改為加上伺服器名稱
username@servername
就成功了
最近在設定Azure Function的定時觸發類型程式的CRON運算式
寫好之後不太確定自己寫得到底對不對
研究了一下後有兩個做法
本地執行後Console視窗上會寫目前執行中的Timer Trigger Function有哪些
以及列出這個Function之後會執行的五個時間點給你看,如圖:
網站網址:https://crontab.guru/
Azure Function的Timer Trigger文件部分其實就有寫,時間運算式使用的是NCronTab 這個LIB來處理,所以就往「CRON運算式 確認」的方向去google,然後就找到這個網站,
雖然他比Azure少一層秒數的表達式,但也是可以提供一個參考,
直接把打好的表達式輸入進去,就可以看到你寫的會以怎樣的週期去執行:
不知道有沒有人做給Azure Function 用的版本,不然還是比較方便
因為要做重構,需要找出有哪些邏輯是藏在DTO裡面的,
但DTO類別檔又很多,不想一個個找
所以就想寫個console程式來撈
首先把要撈的DLL跟他相依的DLL都複製到要執行的排程執行檔輸出資料夾(通常是bin\debug)
以下程式碼:
public class Worker
{
public void DoWork()
{
System.Reflection.Assembly service = Assembly.LoadFile(@"<你要找的namespace所在的dll的絕對路徑>.dll");
Type[] typelist = service.GetTypes();
var nameHaveDtoTypes = typelist.Where(x => x.Name.ToUpper().EndsWith("DTO"));//你的類別名稱的特徵,例如找DTO就結尾是DTO
foreach (var typeitem in nameHaveDtoTypes)
{
if(typeitem.GetProperties().Any(prop=> !MightBeCouldBeMaybeAutoGeneratedInstanceProperty(prop)))
{
foreach (var prop in typeitem.GetProperties().Where(prop => !MightBeCouldBeMaybeAutoGeneratedInstanceProperty(prop)))
{
//印到畫面跟輸出視窗
Console.WriteLine($"{typeitem.Name},{prop.Name}");
System.Diagnostics.Debug.WriteLine($"{typeitem.Name},{prop.Name}");
}
}
}
}
public bool MightBeCouldBeMaybeAutoGeneratedInstanceProperty(PropertyInfo info)
{
bool mightBe = info.GetGetMethod()
.GetCustomAttributes(
typeof(CompilerGeneratedAttribute),
true
)
.Any();
if (!mightBe)
{
return false;
}
bool maybe = info.DeclaringType
.GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
.Where(f => f.Name.Contains(info.Name))
.Where(f => f.Name.Contains("BackingField"))
.Where(
f => f.GetCustomAttributes(
typeof(CompilerGeneratedAttribute),
true
).Any()
)
.Any();
return maybe;
}
}
參考:
1.LINE群大神指點關鍵字CompilerGeneratedAttribute
這個是指在編譯成DLL時,單純getter setter的屬性上面會有這個tag
https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.compilergeneratedattribute.aspx
2.How to find out if a property is an auto-implemented property with reflection?
https://stackoverflow.com/questions/2210309/how-to-find-out-if-a-property-is-an-auto-implemented-property-with-reflection?lq=1
最近版控系統完全轉到git,但新手上路,很多指令還不是很熟,
所以寫一篇筆記方便查找
git clone <target> [<folder name>]
抓下目標到本地(執行位置),可指定新資料夾名稱
git add .
加入目前所有檔案到暫存變更
git commit [-m <message>]
簽入暫存變更帶上簽入訊息
git merge <branch name> --no-ff
做merge但不會fast forword
git log --oneline --graph [-(數字)]
印出線圖 數字可限制印出幾個簽入內的
一個Grid,裡面的row是template,
按鈕除了編輯刪除,其他按鈕案出來的視窗也是template,
在template裡面還有套template,然後都是MVVM去設定事件,
在最尾端的一個表單,要做表單驗證,
有一個欄位是radio button,多選一,當選到某值時另一文字輸入框欄位就變必填
如何在MVVM的model中套用這個特定的required驗證
我原本找到去擴充model binding的binder方法的方向
https://stackoverflow.com/questions/15945755/set-tag-attribute-based-on-variable-value-with-kendo-binding/15947852#15947852
但他要做一個html元件的跟一個widget的,名字還有邏輯,沒搞太懂;
後來轉向套用validator在表單上,雖然不太MVVM,但是可解的方法,
可是這個必填欄位不知為何在執行驗證時會跳
n[t].call is not a function
錯誤,後來發現 不能把validator用的物件放在你的MVVM ViewModel,
他在執行遍歷驗證時會抓到observable的一些屬性但無法辨識(例如_events
)然後就跳那個錯誤,
我本來以為MVVM就是你用到的東西都塞MODEL裡就對了,不過這個情境應該不是這樣放...
再來是自訂驗證規則名稱的雷,
我原本取名PayAccountRequired
,結果竟然讓input不是required也套上required屬性,整個鬼打牆找了很久,後來把規則名稱改成PayAccountRule
,竟然就正常了....
從來沒想到這個驗證會讓我卡好幾個小時....
完成的範例
http://jsfiddle.net/o8ym26jj/2/
情境:
本來寫好一個上傳檔案功能,在本機開發的時候有設定虛擬路徑,檔案在
%USERPROFILE%\documents\IISExpress\config\applicationHost.config
結果最近在側的時候發現怎麼metadata都抓不到了,明明沒有改東西
解法
後來debug了半天發現我的檔案存放路徑不對,
就覺得是虛擬路徑失效的問題,又繼續查,
發現,其實因為中間我的IDE從vs 2013換到vs2015,
結果vs2015好像有個問題就是他不吃上面路徑的設定擋了,
新的設定檔在專案資料夾內的.vs
資料夾(是隱藏資料夾)裡的applicationHost.config
在同樣的區段去新增虛擬路徑就好了
REF: https://forums.asp.net/t/2067764.aspx?VS2015+IIS+Express+cannot+create+virtual+directories
同事在寫的應用:一個GRID裡面有子GRID
資料在展開master row時才會去抓
但不知道怎麼抓
我第一個想法是在master grid展開前先記住外面row的uid,
再用uid反推index,再用index去抓到row,再抓到裡面的grid,但很麻煩;
他研究很久後發現在master grid 的detailInit事件做detail grid宣告,
detail grid裡的databound事件
可以用
$(this.element[0]).data("kendoGrid");
來抓到裡面的grid,簡單明瞭
SELECT
c.name '欄位名稱',
ep.value AS '欄位備註',
t.Name '欄位型態',
c.max_length '最大byte',
c.precision '總位數',
c.scale '小數位數',
c.is_nullable '是否可為空',
ISNULL(i.is_primary_key, 0) '是否是PK'
FROM
sys.columns c
INNER JOIN
sys.types t ON c.user_type_id = t.user_type_id
INNER JOIN sys.objects ON sys.objects.object_id = c.object_id
LEFT OUTER JOIN
sys.index_columns ic ON ic.object_id = c.object_id AND ic.column_id = c.column_id
LEFT OUTER JOIN
sys.indexes i ON ic.object_id = i.object_id AND ic.index_id = i.index_id
OUTER APPLY fn_listextendedproperty(default,
'SCHEMA', schema_name(sys.objects.schema_id),
'TABLE', sys.objects.name, 'COLUMN', c.name) ep
WHERE
c.object_id = OBJECT_ID('your table name')
ref:
https://stackoverflow.com/questions/2418527/sql-server-query-to-get-the-list-of-columns-in-a-table-along-with-data-types-no
https://devio.wordpress.com/2009/08/19/retrieving-table-and-column-descriptions-in-sql-server/
不用
NO
因為要在正式機操作,安全起見才去問&本機測測看....
我原本有個view
在伺服器1 資料庫A (1-A)
跨到伺服器1 資料庫B (1-B)
現在這個view移到 伺服器2 資料庫A (2-A) 跨到1-B
建好1到2的db link後
在ssms更新view的sql並執行,出現一個錯誤訊息:
無法在date上呼叫方法
SQL語法直接按新增查詢是可以跑出來結果,
但在SSMS VIEW的語法設計中執行就會出現這個錯誤
先在GOOGLE找到MSDN上的SQL SERVER錯誤訊息代碼表
https://technet.microsoft.com/zh-tw/library/cc645611(v=sql.105).aspx
然後切成英文,找到關鍵字Cannot Call Methods on
重新搜尋 就找到stackoverflow的討論串
https://stackoverflow.com/questions/16180347/sql-server-cannot-call-methods-on-date
原來是ssms的bug
後來用語法
alter view [view name] as [sql command] 就成功更新了
之前訓練過的筆記,只記在trello,也順便貼過來
我想在下周三請兩小時的假
下周三
、兩小時
--原始欄位:
--民國年數字date_number,時間數字time_number
--(ex:971201,6)
--將民國數字轉西元字串
select cast(970101+19110000 as varchar(8)) --output:20080101
--將西元字串轉YYYY-MM-DD字串
select SUBSTRING(cast(970101+19110000 as varchar(8)),1,4)+'-'
+SUBSTRING(cast(970101+19110000 as varchar(8)),5,2)+'-'
+SUBSTRING(cast(970101+19110000 as varchar(8)),7,2) --output:2008-01-01
--將時分數字PAD成時分秒,在零點時可能只有個位數 如 00:06 =6
select REPLACE(STR(cast(6 as varchar(6)), 6), SPACE(1), '0') --output:000006
--將補齊的時分秒轉為HH:MM:SS字串
select substring(REPLACE(STR(cast(6 as varchar(6)), 6), SPACE(1), '0') ,1,2)+':'
+substring(REPLACE(STR(cast(6 as varchar(6)), 6), SPACE(1), '0') ,3,2)+':'
+substring(REPLACE(STR(cast(6 as varchar(6)), 6), SPACE(1), '0') ,5,2) --output:00:00:06
--將時間字串與時分秒字串轉為DATETIME
select convert(datetime,
SUBSTRING(cast(970101+19110000 as varchar(8)),1,4)+'-'
+SUBSTRING(cast(970101+19110000 as varchar(8)),5,2)+'-'
+SUBSTRING(cast(970101+19110000 as varchar(8)),7,2)
+' '
+substring(REPLACE(STR(cast(6 as varchar(6)), 6), SPACE(1), '0') ,1,2)+':'
+substring(REPLACE(STR(cast(6 as varchar(6)), 6), SPACE(1), '0') ,3,2)+':'
+substring(REPLACE(STR(cast(6 as varchar(6)), 6), SPACE(1), '0') ,5,2)
,121) --output:2008-01-01 00:00:06.000
當grid使用server端做分頁排序篩選時,查詢的邏輯就是靠ToDataSourceResult
來控制,
所以改不了內容在幹嘛,
當前端Grid需要篩選某日期欄位,該欄位又有時分秒,且使用者不想設定秒數時,
預設的時間篩選欄位只會傳入年月日到後端,時分秒為零,
但這樣在做小於等於或者等於的查詢時就會遇到時分秒不相同而查不到資料的問題,
如果是自己做api,這種小地方可以調整用System.Data.Entity.DbFunctions.TruncateTime()
來過濾時間,但用Telerik的類別處理時就不行了,
後來查到官方的解法如連結
https://docs.telerik.com/kendo-ui/controls/data-management/grid/how-to/filtering/filter-by-date
大致上就是說要在filter menu初始化時,複寫套用的按鈕的事件,
例如原本設"等於"條件時,只會傳入一個邏輯就是相等一個日期時間值,
我們要調整為兩個邏輯,
用大於等於當天的零點零分零秒與 小於等於當天的23點59分59秒兩個條件傳入後端,
這樣就可以避免對不上時間的問題了
filterMenuInit: function (e) {
//當日期條件設定為小於/等於時 只會傳入年月日 不會傳入時分秒
//但這樣會撈不到當天0點之後的資料 所以要幫他加到23:59:59來方便處理
//(因為沒辦法調整語法為trunc time)
var menu = $(e.container);
if (e.field === "ColumnDateTime") {
var firstDropDown = $('[data-bind="value: filters[0].operator"]').data('kendoDropDownList');
menu.find('button[type="submit"]').click(function (ev) {
if (firstDropDown.value() === 'eq') {
ev.preventDefault();
var selectedDate = menu.find('[data-role="datepicker"]').first().data('kendoDatePicker').value();
if (!selectedDate) {
$(ev.target).closest('[data-role="popup"]').data('kendoPopup').close();
return;
}
var startOfFilterDate = new Date(selectedDate.getFullYear(), selectedDate.getMonth(), selectedDate.getDate());
var endOfFilterDate = new Date(selectedDate.getFullYear(), selectedDate.getMonth(), selectedDate.getDate(), 23, 59, 59);
var filter = {
logic: "and",
filters: [
{ field: "ColumnDateTime", operator: "gte", value: startOfFilterDate },
{ field: "ColumnDateTime", operator: "lte", value: endOfFilterDate }
]
};
e.sender.dataSource.filter(filter);
$(ev.target).closest('[data-role="popup"]').data('kendoPopup').close();
return;
} else if (firstDropDown.value() === 'le') {
ev.preventDefault();
var selectedDate = menu.find('[data-role="datepicker"]').first().data('kendoDatePicker').value();
if (!selectedDate) {
$(ev.target).closest('[data-role="popup"]').data('kendoPopup').close();
return;
}
var endOfFilterDate = new Date(selectedDate.getFullYear(), selectedDate.getMonth(), selectedDate.getDate(), 23, 59, 59);
var filter = {
logic: "and",
filters: [
{ field: "ColumnDateTime", operator: "lte", value: endOfFilterDate }
]
};
e.sender.dataSource.filter(filter);
$(ev.target).closest('[data-role="popup"]').data('kendoPopup').close();
return;
}
});
}
},