深入LINQ to SQL
1. linq to sql: 将資料庫中的在應用程式中寫成實體類,并将表與類,列與屬性映射起來。使用DataContext去連接配接資料庫,并将資料緩存起來讓linq去瞎搞,完了自動生成相關指令去進一步操作資料庫
2. DataContext表示LINQ TO SQL 架構的主入口點。用于把查詢語句翻譯成SQL語句,以及把資料從資料庫傳回給調用方和把實體的修改寫入資料庫。
1. 以日志形式記錄DataContext生成的SQL
2. 執行SQL(包括查詢和更新語句)
3. 建立和删除資料庫
注意:執行個體操作中的,映射資料庫的方式,在映射類的前面添加TableAttribute屬性即可實作映射Name屬性指定資料庫中的表的名稱。如:
[Table(Name="Product")]
public class Product
{}
上面是對資料庫中表的映射,另外還有對表中列的映射
如:
[Column(Storage="_id",AutoSync=AutoSync.OnIsert,IsPrimaryKey=true)]
跨關系查詢,執行個體講解
步驟:
1. 在類中增加字段
2. 增加一個實體類
建立資料庫的強類型化視圖
繼承DataContext類,增加我們想要的方法和屬性
1. 第一要求:要實作的就是每次要使用某一張表就直接通路屬性就可以了,而不是再執行個體化DataContext類和使用GetTable<T>方法。
2. 第二要求:将存儲過程作為自定義方法添加到類中。
映射資料庫,如:
[DatabaseAttribute(Name="OneDb"]
public class MydataContext:DataContext
{}
存儲過程的映射,如:
[Function(Name="存儲過程名")]
談談我的感受吧,真TND複雜,相對于手工的建立DataContex類,我更願意使用37講中使用VS自動生成的代碼。手工建立的表類映射和資料庫映射,我隻能實作老師課程中講的查尋功能,沒能耐實作更新功能,糾結喲!
兩個表類和一個繼承DataContext類的MydataContext,代碼如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//必須的兩個類庫
using System.Data.Linq;
using System.Data.Linq.Mapping;
namespace WF38
{
//同樣也映射資料庫中的表
[Table(Name = "employee")]
public class employee
{
//建立跟表中列名同名的字段,也可以自定義,最好是一樣
int bh;//員工編号
string xm;//員工姓名
string xb;//性别
string bm;//部門名稱
int bmbh;//部門編号,外鍵
[Column(Storage="bh",AutoSync=AutoSync.OnInsert,IsPrimaryKey=true)]
public int Bh
{
get { return bh; }
set { bh = value; }
}
[Column(Storage="xm",DbType="Varchar(20)")]//我測試過Name這個屬性參數不能用
public string Xm
{
get { return xm; }
set { xm = value; }
}
[Column(Storage="xb",DbType="Char(2)")]
public string Xb
{
get { return xb; }
set { xb = value; }
}
[Column(Storage = "bm", DbType = "NVarchar(50)")]
public string Bm
{
get { return bm; }
set { bm = value; }
}
//外鍵
[Column(Storage = "bmbh", DbType = "Int")]
public int Bmbh
{
get { return bmbh; }
set { bmbh = value; }
}
private EntityRef<department> dep;//實體引用集合
[Association(Storage = "dep", ThisKey = "Bmbh")]
public department Dep //參考EntityRef <TEntity> 結構
{
get { return dep.Entity; }
set { dep.Entity = value; }
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//必須要引入的類庫
using System.Data.Linq;
using System.Data.Linq.Mapping;
namespace WF38
{
//參考幫助裡的TableAttribute類,映射資料庫中的表,最好是類名=表名
[Table(Name = "department")]
public class department
{
int bmbh;//部門編号
string bmmc;//部門名稱
//映射資料表中的列,參數ColumnAttribute 類,參考AutoSync 枚舉
[Column(Storage="bmbh",IsPrimaryKey=true,DbType="Int NOT NULL")]
public int Bmbh
{
get { return bmbh; }
set { bmbh = value; }
}
[Column(Storage = "bmmc", DbType = "Varchar(50) NOT NULL")]
public string Bmmc
{
get { return bmmc; }
set { bmmc = value; }
}
//參考EntitySet <TEntity> 類
//指定部門下的員工集合
private EntitySet<employee> emp;
[Association(Storage = "emp",OtherKey = "Bmbh")]
public EntitySet<employee> Emp
{
get { return emp; }
set { this.emp.Assign(value); }
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//必須的兩個類庫
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Reflection;
namespace WF38
{
//映射資料庫,并且繼承DataContext類
[DatabaseAttribute(Name = "hrms")]
public class MydataContext : DataContext
{
//資料庫中的表作為此資料庫類的字段屬性
Table<department> _department;//部門表
Table<employee> _employee;//員工表
public Table<department> Department
{
get { return _department; }
}
public Table<employee> Employee
{
get { return _employee; }
}
//資料庫連接配接字元串,必須是靜态的,否則下面的構造函數:base()報錯
static string strconn = "server=.; database=hrms; uid=sa; pwd=123123;";
//構造函數
public MydataContext()
: base(strconn)
{
this._department = base.GetTable<department>();
this._employee = base.GetTable<employee>();
}
//對存儲過程的操作
//映射資料庫中的存儲過程(無參數)
[Function(Name="All_employee")]
public Table<employee> All_employee()
{
IExecuteResult result = ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())));
return (Table<employee>)result.ReturnValue;
}
//映射存儲過程(帶參數),注意參數的寫法
[Function(Name = "Delete_employee")]
public int Delete_employee([Parameter(DbType="Int")] Nullable<int> id)
{
IExecuteResult result = ExecuteMethodCall(this,((MethodInfo)MethodInfo.GetCurrentMethod()),id);
return (int)result.ReturnValue;
}
//映射存儲過程(多參數),且有傳回值
[Function(Name = "Add_employee_bh")]
public int Add_employee_bh(
[Parameter(DbType="int")] ref Nullable<int> id,
[Parameter(DbType="Nvarchar(50)")] string xm,
[Parameter(DbType="Char(2)")] string xb,
[Parameter(DbType="Nvarchar(50)")] string bm,
[Parameter(DbType="int")] int bmbh
)
{
IExecuteResult result=ExecuteMethodCall(this,((MethodInfo)MethodInfo.GetCurrentMethod()),id,xm,xb,bm,bmbh);
id=((Nullable<int>)(result.GetParameterValue(0)));
return (int)result.ReturnValue;
}
}
}
前端:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Text.RegularExpressions;
namespace WF38
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
string strCon = "server=.; database=hrms; uid=sa; pwd=123123;";
private void Form1_Load(object sender, EventArgs e)
{
this.cbClass.Text = "####請選擇部門####";
this.lsbInfo.Items.Clear();
//建立Linq to Sql架構類主入口點對象
DataContext dc = new DataContext(strCon);
//通過DataContext對象擷取employee類型的Table對象
//Table<employee> emps = dc.GetTable<employee>();
//var es = from em in emps
// select em;
//foreach (var em in es)
//{
// lsbInfo.Items.Add(string.Format("姓名({0}),編号({1}),性别({2}),所在部門({3})", em.Xm, em.Bh, em.Xb, em.Bm));
//}
//有個現象說一下,一次隻能完成一個Table的加載,如果将上面的注釋解除,下面的語句将不再執行
//是以如果要同時加載,就隻能利用表間關系進行加載
Table<department> deps = dc.GetTable<department>();
var dep = from d in deps
select d;
foreach (var de in dep)
{
cbClass.Items.Add(de.Bmmc.Trim());
foreach (var em in de.Emp)
{
lsbInfo.Items.Add(string.Format("姓名({0}),編号({1}),性别({2}),所在部門({3})", em.Xm, em.Bh, em.Xb, em.Bm));
}
}
}
/// <summary>
/// 員工按部門篩選
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void cbClass_SelectedIndexChanged(object sender, EventArgs e)
{
this.lsbInfo.Focus();
lsbInfo.Items.Clear();
if (this.cbClass.Text != "####請選擇部門####")
{
//建立Linq to Sql架構類主入口點對象
DataContext dc = new DataContext(strCon);
Table<department> deps = dc.GetTable<department>();
string bmmc = cbClass.Text.Trim();
var ems = (from d in deps
where d.Bmmc.Trim() == bmmc
select d).First();
foreach (var em in ems.Emp)
{
lsbInfo.Items.Add(string.Format("姓名({0}),編号({1}),性别({2}),所在部門({3})", em.Xm, em.Bh, em.Xb, em.Bm));
}
}
}
/// <summary>
/// 将選中項資訊更新到下邊的文本框中
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void lsbInfo_SelectedIndexChanged(object sender, EventArgs e)
{
if (lsbInfo.SelectedItems.Count > 0)
{
int s = lsbInfo.Text.Trim().IndexOf("編号");
string str = lsbInfo.Text.Trim().Remove(0, s);
int x = str.IndexOf("(");
int y = str.IndexOf(")");
string bh = str.Substring(x+1, y-3);
//建立Linq to Sql架構類主入口點對象
//DataContext dc = new DataContext(strCon);
//Table<employee> emps = dc.GetTable<employee>();
MydataContext mdc = new MydataContext();//測試手工建立的MydataContext類
var em = (from ep in mdc.Employee
where ep.Bh == int.Parse(bh)
select ep).First();
tbId.Text = em.Bh.ToString();
tbName.Text = em.Xm.Trim();
tbPrice.Text = em.Xb.Trim();
tbClass.Text = em.Bm.Trim();
}
}
/// <summary>
/// 添加員工資訊
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnAdd_Click(object sender, EventArgs e)
{
if (this.cbClass.Text != "####請選擇部門####")
{
string txt = @"^\d*\b$";
Regex reg = new Regex(txt);
if (reg.IsMatch(tbId.Text.Trim()))
{
int bh = int.Parse(tbId.Text.Trim());
string bm = cbClass.Text.Trim();
string xm = tbName.Text.Trim();
string xb = tbPrice.Text.Trim() == "男" ? "男" : "女";
//這裡關鍵兩個表的外鍵部門編号要通過部門名稱來擷取
//建立Linq to Sql架構類主入口點對象
//DataContext dc = new DataContext(strCon);
//Table<department> deps = dc.GetTable<department>();
//int num = (from d in deps
// where d.Bmmc.Trim() == bm
// select d.Bmbh).First();
MydataContext mdc = new MydataContext();
int num = (from d in mdc.Employee
where d.Bmbh.ToString().Trim() == bm
select d.Bmbh
).First();
employee em = new employee();
em.Bh = bh;
em.Xm = xm;
em.Xb = xb;
em.Bm = xm;
em.Bmbh = num;
//這次卡在這裡了,因為老師的示範就這些,我想做成跟VS自動生成代碼
//那樣的效果,但是水準有限,苦思了且嘗試過些方法,結果還是沒搞定
//InsertAllOnSubmit這個方法就是不能執行,老報錯。
//Table<employee> emp = dc.GetTable<employee>();
//mdc.Employee.InsertAllOnSubmit((employee)em);
}
else {
MessageBox.Show("員工工号中存在非數字元号");
}
}
else {
MessageBox.Show("請在上方清單中選擇新員工所在的部門");
}
}
}
}
此執行個體未完功,望高手指定,如何實作DataContext類的更新功能。