自定义配置LINQ的ORM实体类

我不太喜欢直接拖微软的东西,就像拖控件一样,觉得那是刚刚入门的菜鸟才做的,我喜欢自定义配置,这样的配置可以灵活多样,满足自己的独特需求。当然,如果公司特别赶时间的话,使用拖过来的东西也未尝不可。不过往往所谓的赶时间,都是PM等不能很好的安排人员、不能很好的组织需求而导致,或者他是一个XP(极限编程)的倡导者。

这次以一个简单的例子来实现自定义配置LINQ实体类。

数据库就简单的以学校管理系统中的学生和班级为例。只拥有学生和班级两个实体。
TSQL
 1 use master 
2 if exists(select * from sys.databases where [name] ='SchoolManager' )
3 drop database SchoolManager
4
5 CREATE DATABASE SchoolManager --数据库的真实名称
6 on primary --数据库的基本信息 primary 可选的 主要的
7 (
8 NAME = 'SchoolManager_data',--逻辑名称
9 FILENAME ='E:\资料工具\技术资料学习记录\another\SchoolManager_Mdata.mdf',--主数据库文件的目录
10 SIZE = 5mb, --数据库的初始大小
11 FILEGROWTH =5mb--自动增长的标准
12 )
13 log on --一个数据库必须要有的是一个主数据文件和一个日志文件
14 (
15 NAME='SchoolManager_log',
16 FILENAME = 'E:\资料工具\技术资料学习记录\another\SchoolManager_Ldata.ldf',
17 SIZE = 5mb ,
18 FILEGROWTH = 5mb
19 )
20 go
21
22 use SchoolManager
23 if exists (select * from sys.tables where [name]='MyClass')
24 drop table MyClass
25 create table MyClass
26 (
27 class_no varchar(25) primary key not null,---
28 class_name varchar(200) not null
29 )
30
31 if exists(select * from sys.tables where [name] = 'MyStudent')
32 drop table MyStudent
33 create table MyStudent
34 (
35 stu_no varchar(25) primary key not null,
36 stu_name varchar(50) not null,
37 stu_age int ,
38 stu_sex bit ,--true is female ,false is male
39 stu_address varchar(500) ,
40 stu_class_no varchar(25) not null --班级编号,外键
41 )
42 如若需要建立外键关系,可以使用下面语句。
43
44 ----建立外键关系
45 ALTER TABLE MyStudent ADD CONSTRAINT FK_mystudent_myclass
46 FOREIGN KEY (stu_class_no)
47 REFERENCES MyClass(class_no);
48 --删除外键
49 ALTER TABLE MyStudent DROP CONSTRAINT FK_mystudent_myclass
 
如果是要使用VS自带的LINQTOSQL以拖动的方式生成类的话,那么是必须建立外键关系的,当然,在这里我就不建立外键关系了,需要班级和学生在逻辑上是拥有这层一对多的关系,但是并不一定需要建立物理关系,这是方便以后做数据管理。
 
建立一个项目,然后对项目添加System.Data.Linq的引用。为各个数据库和表的映射类引入命名空间
using System.Data.Linq.Mapping;//映射关系配置命名空间
using System.Data.Linq;//Linq查询和一对多关系、多对一关系命名空间
1、添加班级类:
 
View Code
 1 [Serializable()]
2 [Table(Name = "MyClass")]
3 ///<summary>
4 /// 班级 模型,对应MyClass表
5 ///</summary>
6 public class MyClass
7 {
8 private string _classNo;
9
10 [Column(CanBeNull = false, DbType = "varchar(25)", IsPrimaryKey = true
11 , Name = "class_no", Storage = "_classNo")]
12 ///<summary>
13 /// 班级编号
14 ///</summary>
15 public string ClassNo
16 {
17 get { return _classNo; }
18 set { _classNo = value; }
19 }
20
21 private string _className;
22
23
24 [Column(CanBeNull = false, DbType = "varchar(200)", Name = "class_name", Storage = "_className")]
25 ///<summary>
26 /// 班级名称
27 ///</summary>
28 public string ClassName
29 {
30 get { return _className; }
31 set { _className = value; }
32 }
33
34 private EntitySet<Student> _students =new EntitySet<Student>();
35
36 [Association(OtherKey = "MyClass", Storage = "_students", ThisKey = "ClassNo")]
37 ///<summary>
38 /// 学生集合
39 ///</summary>
40 public EntitySet<Student> Students
41 {
42 get { return _students; }
43 set { _students = value; }
44 }
45 }
2、添加学生类
View Code
 1 [Serializable()]
2 [Table(Name = "MyStudent")]
3 ///<summary>
4 /// 学生 模型,对应MyStudent表
5 ///</summary>
6 public class Student
7 {
8 private string _stuNo;
9
10 [Column(CanBeNull = false, DbType = "varchar(25)", IsPrimaryKey = true
11 , Name = "stu_no", Storage = "_stuNo")]
12 ///<summary>
13 /// 学生编号
14 ///</summary>
15 public string StuNo
16 {
17 get { return _stuNo; }
18 set { _stuNo = value; }
19 }
20
21
22 private string _stuName;
23
24 [Column(CanBeNull = false, DbType = "varchar(200)", Name = "stu_name", Storage = "_stuName")]
25 ///<summary>
26 /// 学生姓名
27 ///</summary>
28 public string StuName
29 {
30 get { return _stuName; }
31 set { _stuName = value; }
32 }
33
34 private Sex _stuSex;
35
36 [Column(CanBeNull = false, DbType = "bit", Name = "stu_sex", Storage = "_stuSex")]
37 ///<summary>
38 /// 学生性别,true为女,false为男
39 ///</summary>
40 public Sex StuSex
41 {
42 get { return _stuSex; }
43 set { _stuSex = value; }
44 }
45
46 private Nullable<int> _stuAge;
47
48 [Column(DbType = "int", Name = "stu_age", Storage = "_stuAge")]
49 ///<summary>
50 /// 学生年龄,可为空
51 ///</summary>
52 public Nullable< int> StuAge
53 {
54 get { return _stuAge; }
55 set { _stuAge = value; }
56 }
57
58 private string _stuAddress;
59
60 [Column(DbType = "varchar(500)", Name = "stu_address", Storage = "_stuAddress")]
61 ///<summary>
62 /// 学生住址,可为空
63 ///</summary>
64 public string StuAddress
65 {
66 get { return _stuAddress; }
67 set { _stuAddress = value; }
68 }
69
70 private string _classNo;
71
72 [Column(Name = "stu_class_no", Storage = "_classNo",CanBeNull=false)]
73 public string ClassNo
74 {
75 get { return _classNo; }
76 set { _classNo = value; }
77 }
78
79 private EntityRef<MyClass> _myClass =new EntityRef<MyClass>();
80
81 [Association(IsForeignKey = true, Storage = "_myClass", ThisKey = "ClassNo")]
82 ///<summary>
83 /// 学生所在班级,
84 ///</summary>
85 public MyClass MyClass
86 {
87 /*这里需要重点注意*/
88 get { return _myClass.Entity; }
89 set { _myClass.Entity = value; }
90 }
91
92 }
 
3、添加数据库类
View Code
 1 [Database(Name = "SchoolManager")]
2 ///<summary>
3 /// 数据库对象
4 ///</summary>
5 public class SchoolManager : DataContext
6 {
7
8 //public SchoolManager()
9 // : base(@"E:\资料工具\技术资料学习记录\another\SchoolManager_Mdata.mdf")
10 //{
11 //}
12 //使用这种连接方式一直跑出无法连接的40错误,有谁可以指教。
13 public SchoolManager()
14 : base("server=localhost;uid=sa;pwd=sa;database=SchoolManager;")
15 {
16
17 }
18 public SchoolManager(string connection)
19 : base(connection)
20 {
21
22 }
23
24 ///<summary>
25 /// 班级表
26 ///</summary>
27 public Table<MyClass> MyClass ;
28
29 ///<summary>
30 /// 学生表
31 ///</summary>
32 public Table<Student> Student;
33 }
在各个实体类中的特性,是不同的映射关系,表示映射到表,映射到库,映射到列。要使用一对多或者多对一,或者多对多就需要使用
Association 这个特性,关系特性。
最后实现增删改查
如果学生类中的ClassNo属性配置成为可以为CanBeNull is true 的话,就可以单独添加学生而不为其制定班级,都则就必须为学生指定班级。
//获得一个班级
public static void GetClass()
        {
            SchoolManager sm = new SchoolManager();
            var list = from c in sm.MyClass
                       select c;
            Console.WriteLine(list.FirstOrDefault().ClassName);
        }
//添加一个班级
public static void AddClass()
        {
            MyClass cla = new MyClass();
            cla.ClassName = "001";
            cla.ClassNo = "001";
            SchoolManager sm = new SchoolManager();
            sm.MyClass.InsertOnSubmit(cla);
            sm.SubmitChanges();
        }
//通过班级添加学生
public static void AddStudentByClass()
        {
            MyClass cla = new MyClass();
            cla.ClassName = "002";
            cla.ClassNo = "002";
 
            Student stu = new Student();
            stu.MyClass = cla;
            stu.StuAddress = "广州";
            stu.StuAge = 10;
            stu.StuName = "肖";
            stu.StuNo = "00201";
            stu.StuSex = Sex.Male;
            SchoolManager sm = new SchoolManager();
            sm.MyClass.InsertOnSubmit(cla);
            sm.SubmitChanges();
        }
 
//通过添加学生来添加班级
  public static void AddClassByStu()
        {
            MyClass cla = new MyClass();
            cla.ClassName = "003";
            cla.ClassNo = "003";
 
            Student stu = new Student();
            stu.MyClass = cla;
            stu.StuAddress = "广州";
           // stu.StuAge = 10;
            stu.StuName = "陈";
            stu.StuNo = "00301";
            stu.StuSex = Sex.Female;
 
            SchoolManager sm = new SchoolManager();
            sm.Student.InsertOnSubmit(stu);
            sm.SubmitChanges();
        }
 
对于C#来说,枚举是个很直观并且很好用的东西,如果是拖出来的类,那么就不好使用枚举了,别人都无法通过代码知道0,1到底是男是女。
 /// <summary>
    /// 性别的枚举
    /// </summary>
    public enum Sex
    {
        Female = 0,
        Male = 1
    }
至此配置完毕。
功能实现。
下次讲述JAVA中如何配置JPA映射。让大家了解了解JAVA和C#的异同所在。
切忌,千万别一直做“拖”出来的菜鸟。
 
附源码 LinqDemo https://files.cnblogs.com/xwb2535/LinqDemo.zip 
原文地址:https://www.cnblogs.com/xwb2535/p/2228214.html