C#教程
主页 > 软件编程 > C#教程 >

C#内置泛型委托之Func委托介绍

2022-03-14 | 秩名 | 点击:

一、什么是Func委托

Func委托代表有返回类型的委托

二、Func委托定义

查看Func的定义:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

using System.Runtime.CompilerServices;

 

namespace System

{

    //

    // 摘要:

    //     封装一个方法,该方法具有两个参数,并返回由 TResult 参数指定的类型的值。

    //

    // 参数:

    //   arg1:

    //     此委托封装的方法的第一个参数。

    //

    //   arg2:

    //     此委托封装的方法的第二个参数。

    //

    // 类型参数:

    //   T1:

    //     此委托封装的方法的第一个参数的类型。

    //

    //   T2:

    //     此委托封装的方法的第二个参数的类型。

    //

    //   TResult:

    //     此委托封装的方法的返回值类型。

    //

    // 返回结果:

    //     此委托封装的方法的返回值。

    [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")]

    public delegate TResult Func<in T1, in T2, out TResult>(T1 arg1, T2 arg2);

}

你会发现,Func其实就是有多个输出参数并且有返回值的delegate。

3、示例

Func至少0个输入参数,至多16个输入参数,根据返回值泛型返回。必须有返回值,不可void。

Func<int> 表示没有输入参参,返回值为int类型的委托。

Func<object,string,int> 表示传入参数为object, string ,返回值为int类型的委托。

Func<object,string,int> 表示传入参数为object, string, 返回值为int类型的委托。

Func<T1,T2,,T3,int> 表示传入参数为T1,T2,,T3(泛型),返回值为int类型的委托。

代码示例如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

 

namespace FunDemo

{

    class Program

    {

        static void Main(string[] args)

        {

            // 无参数,只要返回值

            Func<int> fun1 = new Func<int>(FunWithNoPara);

            int result1= fun1();

            Console.WriteLine(result1);

            Console.WriteLine("----------------------------");

            Func<int> fun2 = delegate { return 19; };

            int result2 = fun2();

            Console.WriteLine(result2);

            Console.WriteLine("----------------------------");

            Func<int> fun3 = () => { return 3; };

            int result3 = fun3();

            Console.WriteLine(result3);

            Console.WriteLine("----------------------------");

            //有一个参数,一个返回值

            Func<int, int> fun4 = new Func<int, int>(FunWithPara);

            int result4 = fun4(4);

            Console.WriteLine($"这里是一个参数一个返回值的方法,返回值是:{result4}");

            Console.WriteLine("----------------------------");

            // 使用委托

            Func<int, string> fun5 = delegate (int i) { return i.ToString(); };

            string result5 = fun5(5);

            Console.WriteLine($"这里是一个参数一个返回值的委托,返回值是:{result5}");

            Console.WriteLine("----------------------------");

            // 使用匿名委托

            Func<int, string> fun6 = (int i) =>

            {

                return i.ToString();

            };

            string result6 = fun6(6);

            Console.WriteLine($"这里是一个参数一个返回值的匿名委托,返回值是:{result6}");

            Console.WriteLine("----------------------------");

            // 多个输入参数

            Func<int, string, bool> fun7 = new Func<int, string, bool>(FunWithMultiPara);

            bool result7 = fun7(2, "2");

            Console.WriteLine($"这里是有多个输入参数的方法,返回值是:{result7}");

            Console.WriteLine("----------------------------");

            // 使用委托

            Func<int, string, bool> fun8 = delegate (int i, string s)

            {

                return i.ToString().Equals(s) ? true : false;

            };

            bool result8 = fun8(2, "abc");

            Console.WriteLine($"这里是有多个输入参数的委托,返回值是:{result8}");

            Console.WriteLine("----------------------------");

            // 使用匿名委托

            Func<int, string, bool> fun9 = (int i, string s) =>

            {

                return i.ToString().Equals(s) ? true : false;

            };

            bool result9 = fun9(45, "ert");

            Console.WriteLine($"这里是有多个输入参数的匿名委托,返回值是:{result9}");

            Console.ReadKey();

 

        }

 

        static int FunWithNoPara()

        {

            return 10;

        }

 

        static int FunWithPara(int i)

        {

            return i;

        }

 

        static bool FunWithMultiPara(int i,string s)

        {

            return i.ToString().Equals(s) ? true : false;

        }

    }

}

运行结果:

4、真实示例

在下面的示例中,利用Func委托封装数据库通用访问类。

1、定义BaseModel基类

1

2

3

4

5

6

7

8

9

10

11

12

13

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

 

namespace FunApplication.Model

{

    public class BaseModel

    {

        public int Id { get; set; }

    }

}

2、定义Student类继承自BaseModel基类

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

 

namespace FunApplication.Model

{

    public class Student : BaseModel

    {

        public string Name { get; set; }

 

        public int Age { get; set; }

 

        public int Sex { get; set; }

 

        public string Email { get; set; }

    }

}

3、定义数据库访问方法接口

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

using FunApplication.Model;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

 

namespace FunApplication.IDAL

{

    public interface IBaseDAL

    {

        T Query<T>(int id) where T : BaseModel;

 

        List<T> QueryAll<T>() where T : BaseModel;

 

        int Insert<T>(T t) where T : BaseModel;

 

        int Update<T>(T t) where T : BaseModel;

 

        int Delete<T>(int id) where T : BaseModel;

    }

}

4、定义属性帮助类

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

using System;

using System.Collections.Generic;

using System.Linq;

using System.Reflection;

using System.Text;

using System.Threading.Tasks;

 

namespace FunApplication.AttributeExtend

{

    public static class AttributeHelper

    {

        public static string GetColumnName(this PropertyInfo prop)

        {

            if (prop.IsDefined(typeof(ColumnAttribute), true))

            {

                ColumnAttribute attribute = (ColumnAttribute)prop.GetCustomAttribute(typeof(ColumnAttribute), true);

                return attribute.GetColumnName();

            }

            else

            {

                return prop.Name;

            }

        }

    }

}

5、定义ColumnAttribute类

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

 

namespace FunApplication.AttributeExtend

{

    [AttributeUsage(AttributeTargets.Property)]

    public class ColumnAttribute : Attribute

    {

        public ColumnAttribute(string name)

        {

            this._Name = name;

        }

 

        private string _Name = null;

        public string GetColumnName()

        {

            return this._Name;

        }

    }

}

6、定义数据库方法接口实现类

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

using FunApplication.IDAL;

using FunApplication.Model;

using System;

using System.Collections.Generic;

using System.Configuration;

using System.Data.SqlClient;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Reflection;

using FunApplication.AttributeExtend;

 

namespace FunApplication.DAL

{

    public  class BaseDAL : IBaseDAL

    {

        // 数据库链接字符串

        private static string strConn = ConfigurationManager.ConnectionStrings["DbConnection"].ConnectionString;

        public  int Delete<T>(int id) where T : BaseModel

        {

            int result = 0;

 

            using (SqlConnection conn = new SqlConnection(strConn))

            {

                string strSQL = "delete from Student where Id=@Id";

                SqlParameter para = new SqlParameter("Id", id);

                SqlCommand command = new SqlCommand(strSQL, conn);

                command.Parameters.Add(para);

                conn.Open();

                result = command.ExecuteNonQuery();

            }

            return result;

        }

 

        public int Insert<T>(T t) where T : BaseModel

        {

            int result = 0;

            using (SqlConnection conn = new SqlConnection(strConn))

            {

                Type type = typeof(T);

                var propArray = type.GetProperties().Where(p => p.Name != "Id");

                string strSQL = "insert into Student Values (@Name,@Age,@Sex,@Email) ";

                SqlCommand command = new SqlCommand(strSQL, conn);

                var parameters = propArray.Select(p => new SqlParameter($"@{p.GetColumnName()}", p.GetValue(t) ?? DBNull.Value)).ToArray();

                command.Parameters.AddRange(parameters);

                conn.Open();

                result = command.ExecuteNonQuery();

            }

                return result;

        }

 

        public T Query<T>(int id) where T : BaseModel

        {

            Type type = typeof(T);

            string columnString = string.Join(",", type.GetProperties().Select(p => $"[{p.GetColumnName()}]"));

            string sql = $"SELECT {columnString} FROM [{type.Name}] WHERE Id={id}";

            T t = null;// (T)Activator.CreateInstance(type);

 

            using (SqlConnection conn = new SqlConnection(strConn))

            {

                SqlCommand command = new SqlCommand(sql, conn);

                conn.Open();

                SqlDataReader reader = command.ExecuteReader();

                List<T> list = this.ReaderToList<T>(reader);

                t = list.FirstOrDefault();         

            }

            return t;

        }

 

        public List<T> QueryAll<T>() where T : BaseModel

        {

            Type type = typeof(T);

            string columnString = string.Join(",", type.GetProperties().Select(p => $"[{p.GetColumnName()}]"));

            string sql = $"SELECT {columnString} FROM [{type.Name}] ";

            List<T> list = new List<T>();

            using (SqlConnection conn = new SqlConnection(strConn))

            {

                SqlCommand command = new SqlCommand(sql, conn);

                conn.Open();

                SqlDataReader reader = command.ExecuteReader();

                list = this.ReaderToList<T>(reader);

            }

            return list;

        }

 

        public int Update<T>(T t) where T : BaseModel

        {

            int result = 0;

            using (SqlConnection conn = new SqlConnection(strConn))

            {

                Type type = typeof(T);

                var propArray = type.GetProperties().Where(p => p.Name != "Id");

                string columnString = string.Join(",", propArray.Select(p => $"[{p.GetColumnName()}]=@{p.GetColumnName()}"));

                var parameters = propArray.Select(p => new SqlParameter($"@{p.GetColumnName()}", p.GetValue(t) ?? DBNull.Value)).ToArray();               

                //必须参数化  否则引号?  或者值里面还有引号

                string strSQL = $"UPDATE [{type.Name}] SET {columnString} WHERE Id={t.Id}";

                SqlCommand command = new SqlCommand(strSQL, conn);

                command.Parameters.AddRange(parameters);

                conn.Open();

                result = command.ExecuteNonQuery();           

            }

            return result;

        }

 

        private List<T> ReaderToList<T>(SqlDataReader reader) where T : BaseModel

        {

            Type type = typeof(T);

            List<T> list = new List<T>();

            while (reader.Read())//表示有数据  开始读

            {

                T t = (T)Activator.CreateInstance(type);

                foreach (var prop in type.GetProperties())

                {

                    object oValue = reader[prop.GetColumnName()];

                    if (oValue is DBNull)

                        oValue = null;

                    prop.SetValue(t, oValue);//除了guid和枚举

                }

                list.Add(t);

            }

            return list;

        }

    }

}

7、在Main()方法中调用

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

using FunApplication.DAL;

using FunApplication.Model;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

 

namespace FunApplication

{

    class Program

    {

        static void Main(string[] args)

        {

            #region MyRegion

            BaseDAL dal = new BaseDAL();

            // 查询

            Student student = dal.Query<Student>(2);

            Console.WriteLine($"姓名:{student.Name},年龄:{student.Age},Email地址:{student.Email}");

            Console.WriteLine("----------------------------");

            // 查询所有

            List<Student> list = dal.QueryAll<Student>();

            Console.WriteLine($"集合个数:{list.Count}");

            Console.WriteLine("----------------------------");

            // 插入

            Student studentIns = new Student()

            {

                Name = "小明",

                Age = 20,

                Sex = 2,

                Email = "xiaoming@qq.com"

            };

            bool resultIns = dal.Insert<Student>(studentIns) > 0 ? true : false;

            Console.WriteLine($"插入执行结果:{resultIns}");

            Console.WriteLine("----------------------------");

            // 更新

            Student studentUpd = new Student()

            {

                Id = 1,

                Name = "zhangsan1234",

                Age = 20,

                Sex = 2,

                Email = "zhangsan1234@qq.com"

            };

            bool resultUpd = dal.Update<Student>(studentUpd) > 0 ? true : false;

            Console.WriteLine($"更新执行结果:{resultUpd}");

            Console.WriteLine("----------------------------");

            // 删除

            bool resultDel = dal.Delete<Student>(3) > 0 ? true : false;

            Console.WriteLine($"删除执行结果:{resultDel}");

            #endregion

            Console.ReadKey();

        }

    }

}

8、结果

9、优化

仔细观察上面步骤7中的代码,你会发现在每个方法中都有重复的代码,打开链接,执行SqlCommand命令,那么这些重复的代码能不能提取到一个公共的方法中进行调用呢?答案是可以的,那就是利用Func委托,看下面优化后的代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

using FunApplication.AttributeExtend;

using FunApplication.IDAL;

using FunApplication.Model;

using System;

using System.Collections.Generic;

using System.Configuration;

using System.Data;

using System.Data.SqlClient;

using System.Linq;

using System.Reflection;

using System.Text;

using System.Threading.Tasks;

 

namespace FunApplication.DAL

{

    public class FunBaseDAL : IBaseDAL

    {

        // 数据库链接字符串

        private static string strConn = ConfigurationManager.ConnectionStrings["DbConnection"].ConnectionString;

 

        public int Delete<T>(int id) where T : BaseModel

        {

            Type type = typeof(T);

            string sql = $"delete from {type.Name} where Id=@Id";

            Func<SqlCommand, int> func = (SqlCommand command) =>

            {              

                SqlParameter para = new SqlParameter("Id", id);

                command.Parameters.Add(para);

                return command.ExecuteNonQuery();

            };

 

            return ExcuteSql<int>(sql, func);

        }

 

        public int Insert<T>(T t) where T : BaseModel

        {

            int result = 0;

            Type type = typeof(T);

            var propArray = type.GetProperties().Where(p => p.Name != "Id");

            string strSQL = "insert into Student Values (@Name,@Age,@Sex,@Email) ";

            var parameters = propArray.Select(p => new SqlParameter($"@{p.GetColumnName()}", p.GetValue(t) ?? DBNull.Value)).ToArray();

            Func<SqlCommand, int> func = (SqlCommand command) =>

            {

                command.Parameters.AddRange(parameters);

                return command.ExecuteNonQuery();

            };

            result = ExcuteSql<int>(strSQL, func);

            return result;

        }

 

        public T Query<T>(int id) where T : BaseModel

        {

            Type type = typeof(T);

            string columnString = string.Join(",", type.GetProperties().Select(p => $"[{p.GetColumnName()}]"));

            string sql = $"SELECT {columnString} FROM [{type.Name}] WHERE Id=@Id";

            T t = null;

            DataTable dt = new DataTable();

             

            Func<SqlCommand, T> func = (SqlCommand command) =>

            {

                SqlParameter para = new SqlParameter("@Id", id);

                command.Parameters.Add(para);

                SqlDataAdapter adapter = new SqlDataAdapter(command);

                //SqlDataReader reader = command.ExecuteReader();

                //List<T> list = this.ReaderToList<T>(reader);

                adapter.Fill(dt);

                List<T> list = ConvertToList<T>(dt);

                T tResult = list.FirstOrDefault();

                return tResult;

            };

            t = ExcuteSql<T>(sql, func);

            return t;

        }

 

        public List<T> QueryAll<T>() where T : BaseModel

        {

            Type type = typeof(T);

            string columnString = string.Join(",", type.GetProperties().Select(p => $"[{p.GetColumnName()}]"));

            string sql = $"SELECT {columnString} FROM [{type.Name}] ";

            T t = null;

 

            Func<SqlCommand, List<T>> func = (SqlCommand command) =>

            {

                SqlDataReader reader = command.ExecuteReader();

                List<T> list = this.ReaderToList<T>(reader);

                return list;

            };

            return ExcuteSql<List<T>>(sql, func);

        }

 

        public int Update<T>(T t) where T : BaseModel

        {

            int result = 0;

            Type type = typeof(T);

            var propArray = type.GetProperties().Where(p => p.Name != "Id");

            string columnString = string.Join(",", propArray.Select(p => $"[{p.GetColumnName()}]=@{p.GetColumnName()}"));

            var parameters = propArray.Select(p => new SqlParameter($"@{p.GetColumnName()}", p.GetValue(t) ?? DBNull.Value)).ToArray();

            //必须参数化  否则引号?  或者值里面还有引号

            string strSQL = $"UPDATE [{type.Name}] SET {columnString} WHERE Id={t.Id}";

            Func<SqlCommand, int> func = (SqlCommand command) =>

            {

                command.Parameters.AddRange(parameters);

                return command.ExecuteNonQuery();

            };

            result = ExcuteSql<int>(strSQL, func);

            return result;

        }

 

 

        //多个方法里面重复对数据库的访问  想通过委托解耦,去掉重复代码

        private T ExcuteSql<T>(string sql, Func<SqlCommand, T> func)

        {

            using (SqlConnection conn = new SqlConnection(strConn))

            {

                using (SqlCommand command = new SqlCommand(sql, conn))

                {

                    conn.Open();

                    SqlTransaction sqlTransaction = conn.BeginTransaction();

                    try

                    {

                        command.Transaction = sqlTransaction;

                        T tResult = func.Invoke(command);

                        sqlTransaction.Commit();

                        return tResult;

                    }

                    catch (Exception ex)

                    {

                        sqlTransaction.Rollback();

                        throw;

                    }

                }

            }

        }

 

        private List<T> ReaderToList<T>(SqlDataReader reader) where T : BaseModel

        {

            Type type = typeof(T);

            List<T> list = new List<T>();

            while (reader.Read())//表示有数据  开始读

            {

                T t = (T)Activator.CreateInstance(type);

                foreach (var prop in type.GetProperties())

                {

                    object oValue = reader[prop.GetColumnName()];

                    if (oValue is DBNull)

                        oValue = null;

                    prop.SetValue(t, oValue);//除了guid和枚举

                }

                list.Add(t);

            }

            reader.Close();

            return list;

        }

    }

}

10、在Main()方法中调用

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

using FunApplication.DAL;

using FunApplication.Model;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

 

namespace FunApplication

{

    class Program

    {

        static void Main(string[] args)

        {

            #region 传统实现

            //BaseDAL dal = new BaseDAL();

            //// 查询

            //Student student = dal.Query<Student>(2);

            //Console.WriteLine($"姓名:{student.Name},年龄:{student.Age},Email地址:{student.Email}");

            //Console.WriteLine("----------------------------");

            //// 查询所有

            //List<Student> list = dal.QueryAll<Student>();

            //Console.WriteLine($"集合个数:{list.Count}");

            //Console.WriteLine("----------------------------");

            //// 插入

            //Student studentIns = new Student()

            //{

            //    Name = "小明",

            //    Age = 20,

            //    Sex = 2,

            //    Email = "xiaoming@qq.com"

            //};

            //bool resultIns = dal.Insert<Student>(studentIns) > 0 ? true : false;

            //Console.WriteLine($"插入执行结果:{resultIns}");

            //Console.WriteLine("----------------------------");

            //// 更新

            //Student studentUpd = new Student()

            //{

            //    Id = 1,

            //    Name = "zhangsan1234",

            //    Age = 20,

            //    Sex = 2,

            //    Email = "zhangsan1234@qq.com"

            //};

            //bool resultUpd = dal.Update<Student>(studentUpd) > 1 ? true : false;

            //Console.WriteLine($"更新执行结果:{resultUpd}");

            //Console.WriteLine("----------------------------");

            //// 删除

            //bool resultDel = dal.Delete<Student>(5) > 1 ? true : false;

            //Console.WriteLine($"删除执行结果:{resultDel}");

            #endregion

 

            #region 利用委托

            // 查询

            FunBaseDAL dal = new FunBaseDAL();

            Student student = dal.Query<Student>(1);

            Console.WriteLine($"姓名:{student.Name},年龄:{student.Age},Email地址:{student.Email}");

            Console.WriteLine("----------------------------");

            // 查询所有

            List<Student> list = dal.QueryAll<Student>();

            Console.WriteLine($"集合个数:{list.Count}");

            Console.WriteLine("----------------------------");

            // 插入

            Student studentIns = new Student()

            {

                Name = "tom",

                Age = 19,

                Sex = 1,

                Email = "tom@163.com"

            };

            bool resultIns = dal.Insert<Student>(studentIns) > 0 ? true : false;

            Console.WriteLine($"插入执行结果:{resultIns}");

            Console.WriteLine("----------------------------");

            List<Student> list1 = dal.QueryAll<Student>();

            Console.WriteLine($"插入后集合个数:{list1.Count}");

            Console.WriteLine("----------------------------");

            // 更新

            Student studentUpd = new Student()

            {

                Id = 2,

                Name = "马六123",

                Age = 20,

                Sex = 2,

                Email = "maliu1234@qq.com"

            };

            bool resultUpd = dal.Update<Student>(studentUpd) > 0 ? true : false;

            Console.WriteLine($"更新执行结果:{resultUpd}");

            Console.WriteLine("----------------------------");

            // 删除

            bool resultDel = dal.Delete<Student>(8) > 0 ? true : false;

            Console.WriteLine($"删除执行结果:{resultDel}");

            List<Student> list2 = dal.QueryAll<Student>();

            Console.WriteLine($"删除后集合个数:{list2.Count}");

            Console.WriteLine("----------------------------");

            #endregion

            Console.ReadKey();

        }

    }

}

11、结果

注意

在使用SqlDataReader的时候有时会报错:“已有打开的与此Command相关联的DataReader,必须先将它关闭”。

同时打开两个或循环多个sqldatareader会出现以上错误。因为用的是sqldatareader做数据库的数据读取,sqlconnection开启没有关闭。

一个SqlConnection只能执行一次事务,没用一次必须关闭然后再开启。上面我只用了一次没有关闭,直接开启所以会报错。解决方案有如下两种:

1、其实不用多次打开在开启,那样实现起来很麻烦。直接在连接字符串的后面加上MultipleActiveResultSets=true即可。 配置文件定义如下:

1

2

3

4

5

6

7

8

9

10

11

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

  <connectionStrings>

    <!--<add name="DbConnection" connectionString="Server=.;Initial Catalog=MyDb;User ID=sa;Password=123456;MultipleActiveResultSets=True"/>-->

    <!--配置文件里面添加MultipleActiveResultSets=True-->

    <add name="DbConnection" connectionString="Server=.;Initial Catalog=MyDb;User ID=sa;Password=123456;MultipleActiveResultSets=True"/>

  </connectionStrings>

    <startup>

        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />

    </startup>

</configuration>

2、使用DataTable

在上面是使用的SqlDataReader读取数据,然后转换成List<T>,可以用DataTable代替SqlDataReader,这样就不会报错了,代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

/// <summary>

/// 将DataTable转换成List

/// </summary>

/// <typeparam name="T"></typeparam>

/// <param name="dt"></param>

/// <returns></returns>

private List<T> ConvertToList<T>(DataTable dt) where T:BaseModel

{

      Type type = typeof(T);

      List<T> list = new List<T>();

      foreach(DataRow dr in dt.Rows)

      {

          T t = (T)Activator.CreateInstance(type);

          foreach(PropertyInfo prop in type.GetProperties())

          {

               object value = dr[prop.GetColumnName()];

               if(value is DBNull)

               {

                    value = null;

               }

               prop.SetValue(t, value);

          }

          list.Add(t);

        }

        return list;

}

原文链接:https://www.cnblogs.com/dotnet261010/p/10109837.html
相关文章
最新更新