深入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
{}
存储过程的映射,如:
前端:
此实例未完功,望高手指定,如何实现DataContext类的更新功能。
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类的更新功能。