最近剛學程式,我要到一個程式碼,目前只能大略看出一些輪廓,可是還是不太懂,
希望各為能幫我解答一下,執行結果應該會有500筆資料
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication2
{
class Program
{
public class Seat {
public DateTime ptime { get; set; }
public int Movie { get; set; }
public string Seat_Num { get; set; }
public int soldd { get; set; } //1 表 售出, 0 表未售出
//流水號不用
}
static void Main(string[] args)
{
List<Seat> SeatList = new List<Seat>();
for (int i = 0; i <= 500; i++) //產生500筆資料
{
SeatList.Add((new Seat
{
ptime = DateTime.Now.AddDays(i),
Movie = i+100,
Seat_Num =i.ToString(),
soldd = 0
}));
}
string ConnString = "Data Source=127.0.1;Initial Catalog=Sample666;Integrated Security=True";
SqlConnection conn = new SqlConnection(ConnString);
DataTable dt = new DataTable();
SqlCommand cmd = null;
try
{
dt.Columns.Add("ptime", typeof(DateTime));
dt.Columns.Add("movie", typeof(int));
dt.Columns.Add("seat_num", typeof(string));
dt.Columns.Add("sold", typeof(int));
for (int i = 0; i < SeatList.Count; i++)
{
DataRow dr = dt.NewRow();
//如果有空值會死掉
dr["ptime"] = SeatList[i].ptime;
dr["movie"] = SeatList[i].Movie;
dr["seat_num"] = SeatList[i].Seat_Num;
dr["sold"] = SeatList[i].soldd;
dt.Rows.Add(dr);
}
conn.Open();
using (SqlBulkCopy sqlBC = new SqlBulkCopy(conn))
{
sqlBC.ColumnMappings.Add("ptime", "ptime");
sqlBC.ColumnMappings.Add("movie", "movie");
sqlBC.ColumnMappings.Add("seat_num", "seat_num");
sqlBC.ColumnMappings.Add("sold", "sold");
sqlBC.BatchSize = SeatList.Count;
sqlBC.BulkCopyTimeout = 60;
sqlBC.DestinationTableName = "[seats]";
sqlBC.WriteToServer(dt);
}
}
catch (Exception ex)
{
}
finally
{
conn.Dispose();
}
}
}
}
第一個for回圈我知道是產生500筆資料,可是第2個for回圈的用意是什麼?我只知道
說他是空值就會error,但還是不太清楚這迴圈的用意,希望能為我講解一下,謝謝。
HI!我針對第二個迴圈講解一下,
如果有不懂的可以在留言提問!
//這個迴圈是在跑第一個迴圈放進SeatList的五百筆資料
for (int i = 0; i < SeatList.Count; i++)
{
//宣告一個DataRow,這個是一個資料行的物件
DataRow dr = dt.NewRow();
//(1)如果有空值會死掉(這邊以下再解釋)
//以下四行做設定,設定該行各欄位(dr["ptime"])的欄位值(SeatList[i].ptime)
dr["ptime"] = SeatList[i].ptime;
dr["movie"] = SeatList[i].Movie;
dr["seat_num"] = SeatList[i].Seat_Num;
dr["sold"] = SeatList[i].soldd;
//(2)之後把該行加進dt
dt.Rows.Add(dr);
}
所以上面那個迴圈的過程就是把第一個迴圈放進SeatList的資料再放進dt中。這時候你可能會出現兩個問號,第一個是標註(1)的地方「為什麼有空值的話會出錯?」再解釋這個前我們先來看看dt怎麼來的:
/*再稍微上方一點的地方,我們宣告了一個資料表的物件dt,
所以我們也才能把剛剛產生出來的欄位放進來。*/
DataTable dt = new DataTable();
接著我們從剛剛宣告dt那一行往下看一下,會有這麼一段:
//這一段主要是在為該資料表增加欄位,並設定該欄位的型態。
//例如日期時間、數字、字串等...
dt.Columns.Add("ptime", typeof(DateTime));
dt.Columns.Add("movie", typeof(int));
dt.Columns.Add("seat_num", typeof(string));
dt.Columns.Add("sold", typeof(int));
好的,那接下來可以說說什麼在標註(1)的地方空值為什麼會出錯,是因為放進去的值不符合該欄位設定的屬性,所以他就會因為錯誤而被捕捉到,跑到catch
中,執行出錯後的程式碼,但目前catch
內的程式碼是空的,所以就沒有執行錯誤處理。
太感謝您的解答了,我想再請問就是第一段的部分,我知道他是
自動實作的屬性,但我不太清楚何時會用到這功能,我只知道這樣是讓我
在裡面宣告的東西設定成唯讀跟唯寫,在來是BulkCopyTimeou=60
這個語法,官方是說如果作業逾時,不會認可交易和目的地資料表中移除所有複製的資料列。那意思是說我這程式執行超過60秒就刪除掉剛剛所複製到的資料嗎?那因為我這支成是所要執行的資料較少,所已其實不用這行應該也可以嗎?
第一段是指List
那部分嗎?那是一個物件導向的概念,先宣告一個class物件存放你說的唯讀和唯寫的變數,之後在以下程式碼去new出那個物件(1),並指定欄位資料放進List
(2)
List<Seat> SeatList = new List<Seat>();
for (int i = 0; i <= 500; i++) //產生500筆資料
{
SeatList.Add((new Seat{ //(1)把物件給new出來
ptime = DateTime.Now.AddDays(i), //(2)設定new出來的物件中的值
Movie = i+100, //(2)
Seat_Num =i.ToString(), //(2)
soldd = 0})); //(2)
}
而那句BulkCopyTimeout=60
也像你說的哦!回復交易的意思就是先前做更動的都不會被承認,如果目前的資料跑的完,就可以不用去設定,但是如果不去設定BulkCopyTimeout
的話預設值是30秒ㄛ!這個要注意一下!
public class Seat {
public DateTime ptime { get; set; }
public int Movie { get; set; }
public string Seat_Num { get; set; }
public int soldd { get; set; } //1 表 售出, 0 表未售出
//流水號不用
}
我是對這段比較好奇,因為我目前大部分都是類似int i = 1;這樣,
還沒有設定說唯讀唯寫這樣,我比較想知道,什麼時候需要為他設定
唯讀唯寫這樣?不然我可能只會單純的設定說 DateTime ptime=XXX
int movie=XXX之類的
那是因為目前程式碼的需求比較簡單,以後如果在還沒放資料前需要預設值(get),或是在設定(set)該值的時候需要為他做些處理,就可以用這兩個屬性做處理。
不好意思!因為現在人在外面,等晚上我再補上程式碼解釋!
這個是存取器的應用,可以讓讀寫的時候變得更有彈性,也能像以下程式碼再取值或設值的時候加一些判斷程式碼,然後因為我舉例滿爛的,所以程式碼有問題可以再提出:D
public class people //做一個人物的class
{
public string name; //在class裡宣告一個姓名字串
public string nameAccessors //做一個字串的存取器
{
get //取值時
{
if(name == null || name == "") //如果name是null或是空的就回傳"未輸入姓名"
{
return "未輸入姓名!";
}
else //否則就回傳姓名的值
{
return name;
}
}
set //設值時
{
//這個value是設值時會自動填入的變數名稱,他的值會傳入你要設定的值。
if (value == "") //這邊判斷如果value等於空的話再寫進去name裡面
{
name = value; //把value的值給name
}
else if(name == null || name == "") //如果value不等於空的話,就判斷name等於null或空就把value的值給name
{
name = value;
}
}
}
}
static void main()
{
//用來放目前的name值
string peopleName;
/*這個存取器的設定會是如下:
get:取name時,如果name的值為空的或是null會預設回傳"未輸入姓名!"
set:設定name時,必須先將原本的name值指定為空才可重新設值*/
//初始化時去呼叫存取器取值,
//peopleName會是"未輸入姓名!"
people Rex = new people();
peopleName = Rex.nameAccessors;
//設定值為"Rex",進入set後value會等於"Rex",所以value不等於空,name這時候也還沒有值,
//peopleName會是"Rex"
Rex.nameAccessors = "Rex";
peopleName = Rex.nameAccessors;
//設定值為"Json",進入set後value會等於"Json",所以value不等於空,但name這時候是"Rex,所以"Json"就不會寫入,
//peopleName會是"Rex"
Rex.nameAccessors = "Json";
peopleName = Rex.nameAccessors;
//這裡設定值為"",進入set後value會等於"",所以value等於空,name就會寫入"",
//peopleName會是""
Rex.nameAccessors = "";
peopleName = Rex.nameAccessors;
//設定值為"Json",進入set後value會等於"Json",所以value不等於空,name這時後又是空的,所以"Json"就會寫入,
//peopleName會是"Json"
Rex.nameAccessors = "Json";
peopleName = Rex.nameAccessors;
}
太感謝您的解答了,這讓我學到不少
我倒是沒這樣用過,
第二個for迴圈是將資料塞到DataTable裡面,
至於 空值就會error,
我覺得應該是Null會error吧,
把Null處理掉就好了。
第一個迴圈,產生500筆資料並塞入到 SeatList 裡面
第二個迴圈,將SeatList的資料塞入到 DataTable 中
為什麼空值會死掉,是因為 DateTime/int 不允許空值
請查看 Exception 的訊息內容,就可以知道是哪一個欄位造成的錯誤囉