天天看點

第三十八講 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類的更新功能。