zoukankan      html  css  js  c++  java
  • 简单实体框架

        今天要说的实体框架并不是 ADO.NET EntityFramework,而是利用特性与反射技术自己来搭建一个简单的实体框架。在来讲之前先说些题外话,我们知道要想使一个项目有更好的健壮性、可移植型,是要将项目分层,不管是c/s,还是b/s框架一般都是三层架构,数据处理层(DAL)、业务逻辑层(BLL)、界面显示层(USL或者UI)。当然根据项目的业务流程可能分个七八层也是常有的事。今天主要讲的是在数据处理层是怎样实现实体架构的。

       言归正传,现在开始构建框架,首先建立数据库,就做一个学生选课信息系统(StudentManage),包括三张表,一个学生信息表(Students),一个课程表(CourseS),一个选课表(SCs),它们之间的关系如下图所示:

     

    好了,数据库建好后,我们到程序中去进行操作,新建一个winform项目

    看一下需要创建的类:

     

    先来构建特性类

     

      1  /// <summary>
    2
    3 /// 表特性类
    4
    5 /// </summary>
    6
    7 [AttributeUsage(AttributeTargets.Class)]//可以对类应用特性
    8
    9 public class TableAttribute:Attribute
    10
    11 {
    12
    13 /// <summary>
    14
    15 /// 表名
    16
    17 /// </summary>
    18
    19 public string TableName
    20
    21 {
    22
    23 get;
    24
    25 set;
    26
    27 }
    28
    29 }
    30
    31 [AttributeUsage(AttributeTargets.Property)]//可以对属性应用特性
    32
    33 public class FieldAttribute : Attribute
    34
    35 {
    36
    37 /// <summary>
    38
    39 /// 字段名
    40
    41 /// </summary>
    42
    43 public string FieldName
    44
    45 {
    46
    47 get;
    48
    49 set;
    50
    51 }
    52
    53 /// <summary>
    54
    55 /// 字段类型
    56
    57 /// </summary>
    58
    59 public SqlDbType FieldType
    60
    61 {
    62
    63 get;
    64
    65 set;
    66
    67 }
    68
    69 /// <summary>
    70
    71 /// 是不是主键
    72
    73 /// </summary>
    74
    75 public bool IsPrimaryKey
    76
    77 {
    78
    79 get;
    80
    81 set;
    82
    83 }
    84
    85 /// <summary>
    86
    87 /// 是否为空
    88
    89 /// </summary>
    90
    91 public bool IsNull
    92
    93 {
    94
    95 get;
    96
    97 set;
    98
    99 }
    100
    101 /// <summary>
    102
    103 /// 是否是自动增长
    104
    105 /// </summary>
    106
    107 public bool IsIdentity
    108
    109 {
    110
    111 get;
    112
    113 set;
    114
    115 }
    116
    117 }
    118
    119 在构建实体类(和表是对应着的):
    120
    121   /// <summary>
    122
    123 /// 空接口,实体类的父类
    124
    125 /// </summary>
    126
    127 public class IEntity
    128
    129 {
    130
    131 }
    132
    133 //学生类
    134
    135  [Table(TableName = "Students")]//表名(注意TableAttribute可以简写为Table)
    136
    137 public class Student:IEntity
    138
    139 {
    140
    141 [Field(FieldName="StudentID",FieldType=SqlDbType.NVarChar,IsPrimaryKey=true)]//字段特性
    142
    143 public string StudentID
    144
    145 {
    146
    147 get;
    148
    149 set;
    150
    151 }
    152
    153 [Field(FieldName="StudentName",FieldType=SqlDbType.NVarChar)]
    154
    155 public string StudentName
    156
    157 {
    158
    159 get;
    160
    161 set;
    162
    163 }
    164
    165 [Field(FieldName="Sex",FieldType=SqlDbType.NVarChar)]
    166
    167 public string Sex
    168
    169 {
    170
    171 get;
    172
    173 set;
    174
    175 }
    176
    177 [Field(FieldName="Age",FieldType=SqlDbType.TinyInt)]
    178
    179 public int Age
    180
    181 {
    182
    183 get;
    184
    185 set;
    186
    187 }
    188
    189 //课程类
    190
    191 [Table(TableName="Courses")]
    192
    193 public class Course:IEntity
    194
    195 {
    196
    197 [Field(FieldName="CourseID",FieldType=SqlDbType.Int,IsPrimaryKey=true,IsIdentity=true)]
    198
    199 public int CourseID
    200
    201 {
    202
    203 get;
    204
    205 set;
    206
    207 }
    208
    209 [Field(FieldName = "CourseName", FieldType = SqlDbType.NVarChar)]
    210
    211 public string CourseName
    212
    213 {
    214
    215 get;
    216
    217 set;
    218
    219 }
    220
    221 }
    222
    223 //选课实体类
    224
    225  [Table(TableName="SCs")]
    226
    227 public class SC:IEntity
    228
    229 {
    230
    231 [Field(FieldName="StudentID",FieldType=SqlDbType.NVarChar,IsPrimaryKey=true)]
    232
    233 public string StudentID
    234
    235 {
    236
    237 get;
    238
    239 set;
    240
    241 }
    242
    243 [Field(FieldName = "CourseID", FieldType = SqlDbType.Int, IsPrimaryKey = true)]
    244
    245 public int CourseID
    246
    247 {
    248
    249 get;
    250
    251 set;
    252
    253 }
    254
    255 }

    好了,实体类构建完成后,我们就来构建实体操作类:

     

      1 public class EntityOPT
    2
    3 {
    4
    5 string constr;//连接字符串
    6
    7 SqlConnection con;//数据库连接
    8
    9 /// <summary>
    10
    11 /// 数据初始化
    12
    13 /// </summary>
    14
    15 public EntityOPT()
    16
    17 {
    18
    19 constr = "server=.;database=StudentManage;uid=sa;pwd=sa"; ;
    20
    21 con = new SqlConnection(constr);
    22
    23 }
    24
    25 /// <summary>
    26
    27 /// 获得表名
    28
    29 /// </summary>
    30
    31 /// <param name="type"></param>
    32
    33 /// <returns></returns>
    34
    35 string GetTableName(Type type)
    36
    37 {
    38
    39 return ((TableAttribute)type.GetCustomAttributes(true)[0]).TableName;//给类只加了一个自定义特性
    40
    41 }
    42
    43 public List<T> QueryAll<T>() where T : IEntity//由于不知道前台会传哪个实体类,所以用泛型
    44
    45 {
    46
    47 try
    48
    49 {
    50
    51 Type type = typeof(T);//得到类型
    52
    53 List<T> entitys = new List<T>();//实体集合
    54
    55 string sql = "select *from " + GetTableName(type);//获得表名,拼接sql语句
    56
    57 SqlDataAdapter da = new SqlDataAdapter(sql, constr);
    58
    59 DataTable dt = new DataTable();
    60
    61 da.Fill(dt);//向DataTable中填充数据
    62
    63 foreach (DataRow row in dt.Rows)//遍历所有行
    64
    65 {
    66
    67 ConstructorInfo conInfo = type.GetConstructor(new Type[0]);//得到构造函数
    68
    69 object obj = conInfo.Invoke(null);//实例化对象
    70
    71 foreach (PropertyInfo pi in type.GetProperties())//得到所有属性
    72
    73 {
    74
    75 foreach (object ob in pi.GetCustomAttributes(true))//遍历字段所有特性
    76
    77 {
    78
    79 if (ob is FieldAttribute)
    80
    81 {
    82
    83 string fieldname = (ob as FieldAttribute).FieldName;//得到表中字段的名字
    84
    85 pi.SetValue(obj, row[fieldname], null);//给实体类属性赋值
    86
    87 break;
    88
    89 }
    90
    91 }
    92
    93 }
    94
    95 entitys.Add((T)obj);
    96
    97 }
    98
    99 return entitys;
    100
    101 }
    102
    103 catch (Exception ex)
    104
    105 {
    106
    107 throw new Exception("数据层查询所有数据发生异常:" + ex.Message);
    108
    109 }
    110
    111 }
    112
    113 /// <summary>
    114
    115 /// 插入数据
    116
    117 /// </summary>
    118
    119 /// <param name="entity"></param>
    120
    121 /// <returns></returns>
    122
    123 public bool InsertEntity(IEntity entity)
    124
    125 {
    126
    127 try
    128
    129 {
    130
    131 Type type = entity.GetType();
    132
    133 List<SqlParameter> pars = new List<SqlParameter>();//sql参数集合
    134
    135 string sql = "insert into " + GetTableName(type) + " values(";
    136
    137 foreach (PropertyInfo pi in type.GetProperties())//遍历类的所有属性
    138
    139 {
    140
    141 foreach (object obj in pi.GetCustomAttributes(true))//遍历属性的特性
    142
    143 {
    144
    145
    146
    147 if (obj is FieldAttribute && !(obj as FieldAttribute).IsIdentity)//有些主键是不自动增长的,如学号
    148
    149 {
    150
    151 string par = "@" + (obj as FieldAttribute).FieldName;
    152
    153 sql += par + ",";//拼接sql语句
    154
    155 SqlParameter sp = new SqlParameter(par, (obj as FieldAttribute).FieldType);
    156
    157 sp.Value = pi.GetValue(entity, null);
    158
    159 pars.Add(sp);
    160
    161 break;
    162
    163 }
    164
    165 }
    166
    167 }
    168
    169 sql = sql.TrimEnd(',') + ")";//去掉多余的逗号
    170
    171 return SaveChange(sql, pars);
    172
    173 }
    174
    175 catch (Exception ex)
    176
    177 {
    178
    179 throw new Exception(ex.Message);
    180
    181 }
    182
    183 }
    184
    185 /// <summary>
    186
    187 /// 删除数据
    188
    189 /// </summary>
    190
    191 /// <param name="entity"></param>
    192
    193 /// <returns></returns>
    194
    195 public bool DeleteEntity(IEntity entity)
    196
    197 {
    198
    199 try
    200
    201 {
    202
    203 Type type = entity.GetType();
    204
    205 List<SqlParameter> sps = new List<SqlParameter>();
    206
    207 string sql = "delete " + GetTableName(type) + " where ";
    208
    209 foreach (PropertyInfo pi in type.GetProperties())
    210
    211 {
    212
    213 foreach (object obj in pi.GetCustomAttributes(true))
    214
    215 {
    216
    217 if (obj is FieldAttribute && (obj as FieldAttribute).IsPrimaryKey)
    218
    219 {
    220
    221 FieldAttribute fa = obj as FieldAttribute;
    222
    223 sql += fa.FieldName + "=@" + fa.FieldName+" and ";//可能会是联合主键
    224
    225 SqlParameter sp = new SqlParameter("@" + fa.FieldName, fa.FieldType);
    226
    227 sp.Value = pi.GetValue(entity, null);
    228
    229 sps.Add(sp);
    230
    231 break;
    232
    233 }
    234
    235 }
    236
    237 }
    238
    239 sql = sql.Substring(0, sql.Length - 4);
    240
    241 return SaveChange(sql,sps);
    242
    243 }
    244
    245 catch (Exception ex)
    246
    247 {
    248
    249 throw new Exception(ex.Message);
    250
    251 }
    252
    253 }
    254
    255 /// <summary>
    256
    257 /// 更新数据
    258
    259 /// </summary>
    260
    261 /// <param name="entity"></param>
    262
    263 /// <returns></returns>
    264
    265 public bool UpdateEntity(IEntity entity)
    266
    267 {
    268
    269 try
    270
    271 {
    272
    273 Type type = entity.GetType();
    274
    275 List<SqlParameter> pars = new List<SqlParameter>();
    276
    277 string sql = "update " + GetTableName(type) + " set ";
    278
    279 string where = " where ";
    280
    281 foreach (PropertyInfo pi in type.GetProperties())
    282
    283 {
    284
    285 foreach (object obj in pi.GetCustomAttributes(true))
    286
    287 {
    288
    289 if (obj is FieldAttribute)
    290
    291 {
    292
    293 FieldAttribute fa = obj as FieldAttribute;
    294
    295 if (fa.IsPrimaryKey)
    296
    297 {
    298
    299
    300
    301 where += fa.FieldName + "=@" + fa.FieldName;
    302
    303 SqlParameter sp = new SqlParameter("@" + fa.FieldName, fa.FieldType);
    304
    305 sp.Value = pi.GetValue(entity, null);
    306
    307 pars.Add(sp);
    308
    309 }
    310
    311 else
    312
    313 {
    314
    315 sql += fa.FieldName + "=@" + fa.FieldName + ",";
    316
    317 SqlParameter sp = new SqlParameter("@" + fa.FieldName, fa.FieldType);
    318
    319 sp.Value = pi.GetValue(entity, null);
    320
    321 pars.Add(sp);
    322
    323 }
    324
    325 break;
    326
    327 }
    328
    329 }
    330
    331 }
    332
    333 sql = sql.TrimEnd(',') + where;
    334
    335 return SaveChange(sql, pars);
    336
    337 }
    338
    339 catch (Exception ex)
    340
    341 {
    342
    343 throw new Exception(ex.Message);
    344
    345 }
    346
    347 }
    348
    349 /// <summary>
    350
    351 /// 向数据库提交数据
    352
    353 /// </summary>
    354
    355 /// <param name="sql"></param>
    356
    357 /// <param name="pars"></param>
    358
    359 /// <returns></returns>
    360
    361 bool SaveChange(string sql, List<SqlParameter> pars)
    362
    363 {
    364
    365 try
    366
    367 {
    368
    369 SqlCommand cmd = new SqlCommand(sql, con);
    370
    371 foreach (SqlParameter par in pars)
    372
    373 {
    374
    375 cmd.Parameters.Add(par);
    376
    377 }
    378
    379 con.Open();
    380
    381 int count = cmd.ExecuteNonQuery();
    382
    383 if (count > 0)
    384
    385 {
    386
    387 return true;
    388
    389 }
    390
    391 else
    392
    393 {
    394
    395 return false;
    396
    397 }
    398
    399 }
    400
    401 catch (Exception ex)
    402
    403 {
    404
    405
    406
    407 throw new Exception(ex.Message);
    408
    409 }
    410
    411 finally
    412
    413 {
    414
    415 con.Close();
    416
    417 }
    418
    419 }
    420
    421
    422
    423 }


    好了,到这一步,一个简单的实体框架算是构建完成,下面来测试。

    先做一个界面:

     

    四个button控件,一个dataGridView控件。

     1 //先来做学生的添加:
    2
    3 Student student = new Student();
    4
    5 student.StudentID = "09040401036";
    6
    7 student.StudentName = "张三";
    8
    9 student.Age = 18;
    10
    11 student.Sex = "";
    12
    13 if (entityopt.InsertEntity(student))
    14
    15 {
    16
    17 MessageBox.Show("添加成功!");
    18
    19 }
    20
    21 else
    22
    23 {
    24
    25 MessageBox.Show("添加失败!");
    26
    27 }
    28
    29 //查询操作:
    30
    31 private void button4_Click(object sender, EventArgs e)
    32
    33 {
    34
    35 dataGridView1.DataSource = entityopt.QueryAll<Student>();
    36
    37 }


    单击添加并查询:

     

    添加成功。

    来做修改,把名字改为李四:

        

     1  Student student = new Student();
    2
    3 student.StudentID = "09040401036";
    4
    5 student.StudentName = "李四";
    6
    7 student.Age = 18;
    8
    9 student.Sex = "";
    10
    11 if (entityopt.UpdateEntity(student))
    12
    13 {
    14
    15 MessageBox.Show("修改成功!");
    16
    17 }
    18
    19 else
    20
    21 {
    22
    23 MessageBox.Show("修改失败!");
    24
    25 }


    单击修改,并查询:

     

    修改成功。

    删除刚才的学生信息:

        

     1             Student student = new Student();
    2
    3 student.StudentID = "09040401036";
    4
    5 if (entityopt.DeleteEntity(student))
    6
    7 {
    8
    9 MessageBox.Show("删除成功!");
    10
    11 }
    12
    13 else
    14
    15 {
    16
    17 MessageBox.Show("删除失败!");
    18
    19 }


         删除并查询:

     

    删除成功。

    下面在对课程操作,首先添加课程:

     1  Course course = new Course();
    2
    3 course.CourseName = "C#";
    4
    5 if (entityopt.InsertEntity(course))
    6
    7 {
    8
    9 MessageBox.Show("添加成功!");
    10
    11 }
    12
    13 else
    14
    15 {
    16
    17 MessageBox.Show("添加失败!");
    18
    19 }
    20
    21 //查询操作:
    22
    23 dataGridView1.DataSource = entityopt.QueryAll<Course>();


        

    点击添加,然后查询,结果:

     

    我们看到课程也添加成功了,在做修改:

     1             Course course = new Course();
    2
    3 course.CourseID = 1;
    4
    5 course.CourseName = "asp.net";
    6
    7 if (entityopt.UpdateEntity(course))
    8
    9 {
    10
    11 MessageBox.Show("修改成功!");
    12
    13 }
    14
    15 else
    16
    17 {
    18
    19 MessageBox.Show("修改失败!");
    20
    21 }


        

    点击修改,并查询,结果:

     

    课程也能修改成功!

    再来删除!

        

     1             Course course = new Course();
    2
    3 course.CourseID = 1;
    4
    5 if (entityopt.DeleteEntity(course))
    6
    7 {
    8
    9 MessageBox.Show("删除成功!");
    10
    11 }
    12
    13 else
    14
    15 {
    16
    17 MessageBox.Show("删除失败!");
    18
    19 }


       看一下运行结果:

      

       删除成功!

    好了,到这一步我们发现实体框架构建成功,并能运行。不过注意了,如果要是做选课的修改时,不能直接调用修改方法,因为它是联合主键,应该先删除在添加,其实修改本本身就是先删除后添加的过程。

    好,今天讲的东西虽然是简单实体框架,但也有难度,一般大公司都有自己的实体框架,有不懂的地方可以和我交流。

    __喜欢的朋友别忘了推荐下,这里先谢了。。 ——我打远古走来,抖一身秦风汉雨,过一程唐关明月。累了,卧一卧高山大川。醒了,嗅一嗅明月星空。
  • 相关阅读:
    《机器学习》第二次作业——第四章学习记录和心得
    机器学习一到三章笔记
    [ML] 第四章学习总结
    [CV] Mnist手写数字分类
    ModelArts (华为GPU/CPU计算云平台)体验
    [DataSturcture] 红黑树求逆序对
    [CV] 边缘提取和角点判断
    [CV] 灰度共生矩阵
    [DataStructure] AC 自动机(Aho–Corasick Automata)
    [GIT] 如何删除git上保存的文件(包含历史文件)
  • 原文地址:https://www.cnblogs.com/yunfeiyang/p/2078533.html
Copyright © 2011-2022 走看看