第三十八讲 LINQ to SQL-续 (手动的写Linq to Sql代码)

深入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类的更新功能。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值