我实现了一个简单的EF框架,主要用于操纵数据库。实现了对数据库的基本操纵--CRUD

这是项目结构 这是一个 core 下的 DLL

写了一个数据库工厂,用于执行sql语句。调用sql语句工厂

写了一个sql语句工厂,用于生成sql语句。调用类型工厂

写了一个类型工厂,用于获取所需的类型,识别特性等。

appsettings.json是配置文件

最后一个是使用说明

我实现过程的首先从底层开始。

首先写的是类型工厂

结构

BaseTypeHelper.cs 是基础的类型帮助类

TypeHelperFactory.cs是一个工厂,调用BaseTypeHelper.cs,是现自己的功能,同时为sql语句工厂提供服务。

首先介绍一下BaseTypeHelper.cs类。这是代码。为TypeHelperFactory提供了必要的服务

  1. public static class BaseTypeHelper
  2. {
  3. #region 获取单个成员
  4. private static MemberInfo GetOneMember(Type t, string MemberName)
  5. {
  6. return GetAllMembers(t).FirstOrDefault(m => m.Name == MemberName);
  7. }
  8.  
  9. #endregion
  10.  
  11. #region 获取所有成员
  12. public static MemberInfo[] GetAllMembers(Type t)
  13. {
  14. return t.GetMembers();
  15. }
  16.  
  17. #endregion
  18.  
  19. #region 获取成员的属性
  20.  
  21. /// <summary>
  22. /// 获取成员的属性
  23. /// </summary>
  24. /// <param name="obj">目标类</param>
  25. /// <param name="MemberName">成员名称</param>
  26. /// <returns></returns>
  27. private static PropertyInfo GetProperty(object obj, string MemberName)
  28. {
  29. var type = obj.GetType();
  30. var member = GetOneMember(type, MemberName);
  31. return type.GetProperty(member.Name);
  32.  
  33. }
  34. #endregion
  35.  
  36. #region 执行法并返回结果
  37. /// <summary>
  38. /// 获取方法的返回值
  39. /// </summary>
  40. /// <param name="MethodName">方法的名称</param>
  41. /// <param name="instance">实例</param>
  42. /// <param name="param">参数列表,如果没有参数则置为null</param>
  43. /// <returns></returns>
  44. public static object GetMethodValue(string MethodName, object instance, params object[] param)
  45. {
  46. Type t = instance.GetType();
  47. try
  48. {
  49. MethodInfo info = t.GetMethod(MethodName);
  50. return info.Invoke(instance, param);
  51. }
  52. catch (Exception e)
  53. {
  54. Console.WriteLine("方法没有找到," + e);
  55. throw;
  56. }
  57.  
  58. }
  59. #endregion
  60.  
  61. #region 获取声明成员的类型
  62.  
  63. /// <summary>
  64. /// 获取声明成员的类型
  65. /// 说明:返回若为空则 没有找到
  66. /// 若不为空,则查找正常
  67. /// </summary>
  68. /// <param name="MemberName">成员的名称</param>
  69. /// <param name="t">所在类的类型</param>
  70. /// <returns></returns>
  71. public static string GetPropertyType(string MemberName, Type t)
  72. {
  73. MemberInfo member = GetOneMember(t, MemberName);
  74. if (member != null)
  75. {
  76. PropertyInfo property = t.GetProperty(member.Name);
  77. return property.PropertyType.Name;
  78. }
  79. return null;
  80.  
  81. }
  82. #endregion
  83.  
  84. #region 获取单个成员是否含有某个属性
  85.  
  86. /// <summary>
  87. /// 获取单个成员是否含有某个特性
  88. /// </summary>
  89. /// <param name="MemberName">成员的名称</param>
  90. /// <param name="t">所在类的类型</param>
  91. /// <param name="attribute">要获取的特性</param>
  92. /// <returns></returns>
  93. public static bool CustomAttributeExist(string MemberName, Type t, Attribute attribute)
  94. {
  95.  
  96. var Member = GetOneMember(t, MemberName);
  97. var My_customAttribute = Member.CustomAttributes.FirstOrDefault(
  98. a => a.AttributeType == attribute.GetType());
  99. return My_customAttribute != null;
  100. }
  101. #endregion
  102.  
  103. #region 通过SetValue给成员设值
  104.  
  105. /// <summary>
  106. /// 给成员设值
  107. /// </summary>
  108. /// <param name="obj">目标类</param>
  109. /// <param name="MemberName">类内属性名称</param>
  110. /// <param name="value">设置的值</param>
  111. public static void SetValue(object obj, string MemberName, object value)
  112. {
  113. var Property = GetProperty(obj, MemberName);
  114. Property.SetValue(obj, value);
  115. }
  116. #endregion
  117.  
  118. #region 通过GetValue给成员取值
  119.  
  120. /// <summary>
  121. /// 取成员的值
  122. /// </summary>
  123. /// <param name="obj">目标类</param>
  124. /// <param name="MemberName">成员的名称</param>
  125. /// <returns></returns>
  126. public static object GetValue(object obj, string MemberName)
  127. {
  128. var Property = GetProperty(obj, MemberName);
  129. return Property.GetValue(obj);
  130. }
  131. #endregion
  132.  
  133. }

BaseTypeHelper.cs

这是TypeHelperFactory.cs 这是一个工厂,利用BaseTypeHelper.cs 提供的服务的基础之上为上层,提供这么几个功能,获取所有的属性列表,获取属性和值的字典集,获取主键(实现了特性[key]的识别,以及默认的ID.toLower()),获取表名(这里获取表名的时候,只是简单的实现了获取类的名称,并没有实现获取特性[Table(Name="...")]这个功能,会在以后更新上去的),获取主键的名称,获取主键的值,获取声明主键的类型,给属性设值。

  1. public static class TypeHelperFactory
  2. {
  3. #region GetAllPropertyList
  4.  
  5. public static List<string> GetAllPropertyList(Type type)
  6. {
  7. var Propertys = BaseTypeHelper
  8. .GetAllMembers(type)
  9. .ToList()
  10. .FindAll(member => member.MemberType == MemberTypes.Property);
  11. var PropertyList = new List<string>();
  12. foreach (var item in Propertys)
  13. {
  14. PropertyList.Add(item.Name);
  15. }
  16. return PropertyList;
  17. }
  18.  
  19. #endregion
  20.  
  21. #region GetAllPropertyNameAndValueDictionary
  22. //添加到字典中的时候已经去除掉空的值
  23. public static Dictionary<string, object> GetAllPropertyNameAndValueDictionary(object obj)
  24. {
  25. Type type = obj.GetType();
  26. var PropertyList = GetAllPropertyList(type);
  27. var PropertyValueList = new Dictionary<string, object>();
  28. foreach (var Property in PropertyList)
  29. {
  30. var value = BaseTypeHelper.GetValue(obj, Property);
  31. if (value == null) continue;
  32. PropertyValueList.Add(Property, value);
  33. }
  34. return PropertyValueList;
  35. }
  36.  
  37. #endregion
  38.  
  39. #region GetTableName
  40. /// <summary>
  41. ///简单获取类的名称
  42. /// 未查找特性[table(Name="")]的标注
  43. /// 2017-5-9 18:00
  44. /// Author :曲
  45. /// </summary>
  46. /// <param name="type"></param>
  47. /// <returns></returns>
  48. public static string GetTableName(Type type)
  49. {
  50. return type.Name;
  51. }
  52.  
  53. #endregion
  54.  
  55. #region GetPrimaryKey
  56.  
  57. public static string GetPrimaryKey(Type type)
  58. {
  59. //1.查找特性标注为key的
  60. //2.如果不存在 查找 类型为int和名称为ID/Id/id 的
  61. var memberNameList = GetAllPropertyList(type);
  62. var attrribute = new KeyAttribute();
  63.  
  64. foreach (var item in memberNameList)
  65. {
  66. if (BaseTypeHelper.CustomAttributeExist(item, type, attrribute))
  67. {
  68. return item;
  69. }
  70. }
  71. return memberNameList.FirstOrDefault(
  72. key => key.ToLower() == "id"
  73. && BaseTypeHelper
  74. .GetPropertyType(key, type)
  75. .Contains("Int")
  76. );
  77.  
  78. }
  79.  
  80. #endregion
  81.  
  82. #region GetPrimaryKeyValue
  83.  
  84. public static object GetPrimaryKeyValue(object obj, string PrimaryKeyName)
  85. {
  86. return BaseTypeHelper.GetValue(obj, PrimaryKeyName);
  87. }
  88.  
  89. #endregion
  90.  
  91. #region GetPrimaryKeyType
  92.  
  93. public static string GetPrimaryKeyType(Type type, string PrimaryKey)
  94. {
  95. return BaseTypeHelper.GetPropertyType(PrimaryKey, type);
  96. }
  97.  
  98. #endregion
  99.  
  100. #region SetPropertyValue
  101.  
  102. public static void SetPropertyValue(object obj, string MemberName, object value)
  103. {
  104. BaseTypeHelper.SetValue(obj, MemberName, value);
  105. }
  106.  
  107. #endregion
  108. }

TypeHelperFactory.cs

接下来写的是sql语句构造工厂,这是工厂结构。

两个文件夹,一个实现接口文件夹,一个接口文件夹。两个类,一个枚举类,一个对外提供服务的类,也就是外界只能通过这一个类,获取我这一层对外提供的服务。

首先介绍一下接口文件夹 :里边定义了接口的类型,以及方法

里边有五个接口,分别是ICreate、IDelete、IRead、IUpdate、ISqlStatementBuilder。

对这五个接口进行说明一下,ISqlStatementBuilder是总的接口,即对外提供服务的接口,分别继承了CURD这四个接口。

  1. public interface ISqlStatementBuilder : ICreate, IRead, IUpdate, IDelete
  2. {
  3.  
  4. }

ISqlStatementBuilder.cs

  1. public interface ICreate
  2. {
  3. string CreateSqlString(object obj);
  4. }

ICreate.cs

  1. public interface IDelete
  2. {
  3. string DeleteSqlString(object obj);
  4.  
  5. }

IDelete.cs

  1. public interface IRead
  2. {
  3. string ReadSqlString(object obj);
  4. }

IRead.cs

  1. public interface IUpdate
  2. {
  3. string UpdateSqlString(object obj);
  4. }

IUpdate.cs

接下来是:实现接口文件夹,这个文件夹包含了三类数据库的对应的sql不同的sql语句。MySql,Oracle,SqlServer,这里我只实现了sqlserver对应的数据库的sql语句。

  1. public class SqlServerSqlStatement :ISqlStatementBuilder
  2. {
  3.  
  4. #region 获取Insertsql语句 实现ICreate接口
  5.  
  6. public string CreateSqlString(object obj)
  7. {
  8. var type = obj.GetType();
  9. var TableName = TypeHelperFactory.GetTableName(type);
  10. var PrimaryKeyName = TypeHelperFactory.GetPrimaryKey(type);
  11. var PropertyNameAndValueDictionary = TypeHelperFactory.GetAllPropertyNameAndValueDictionary(obj);
  12. PropertyNameAndValueDictionary.Remove(PrimaryKeyName);
  13. //这里进行了修改 2017-5-17 17:10
  14. //这是原来的代码
  15. //var PropertyNameList = new List<string>();
  16. //var PropertyValueList = new List<object>();
  17. //foreach (var item in PropertyNameAndValueDictionary)
  18. //{
  19. // PropertyNameList.Add(item.Key);
  20. // PropertyValueList.Add(item.Value);
  21. //}
  22. //这是新的代码 测试已通过 以后考虑用元组实现 2017-5-17 17:15
  23. var PropertyNameList = from item in PropertyNameAndValueDictionary
  24. select item.Key;
  25. var PropertyValueList = from item in PropertyNameAndValueDictionary
  26. select item.Value;
  27. string sql1 = string.Join(",", PropertyNameList);
  28. string sql2 = "'";
  29. sql2 += string.Join("','", PropertyValueList);
  30. sql2 += "'";
  31. var SqlStatement = new StringBuilder();
  32. SqlStatement.AppendFormat($"insert into {TableName} ({sql1}) values ({sql2})");
  33. return SqlStatement.ToString();
  34.  
  35. }
  36.  
  37. #endregion
  38.  
  39. #region 获取Readsql语句 实现IRead接口
  40.  
  41. public string ReadSqlString(object obj)
  42. {
  43. var type = obj.GetType();
  44. var PropertyList = TypeHelperFactory.GetAllPropertyList(type);
  45. var TableName = TypeHelperFactory.GetTableName(type);
  46. string SelectString = string.Join(",", PropertyList);
  47. StringBuilder SqlStatement = new StringBuilder();
  48. SqlStatement.AppendFormat($"select {SelectString} from {TableName}");
  49. return SqlStatement.ToString();
  50. }
  51.  
  52. #endregion
  53.  
  54. #region 获取Updatesql语句 实现IUpdate接口
  55. public string UpdateSqlString(object obj)
  56. {
  57. var type = obj.GetType();
  58. var TableName = TypeHelperFactory.GetTableName(type);
  59. var PrimaryKeyName = TypeHelperFactory.GetPrimaryKey(type);
  60. if (PrimaryKeyName == null)
  61. {
  62. throw new Exception("不存在主键");
  63. }
  64. var PrimaryKeyValue = TypeHelperFactory.GetPrimaryKeyValue(obj, PrimaryKeyName);
  65. var PropertyNameAndValueDictionary = TypeHelperFactory.GetAllPropertyNameAndValueDictionary(obj);
  66. PropertyNameAndValueDictionary.Remove(PrimaryKeyName);
  67. //这里进行了修改 2017-5-17 17:00
  68. //这是原来的代码
  69. //var NameAndValueList = new List<string>();
  70. //foreach (var item in PropertyNameAndValueDictionary)
  71. //{
  72. // NameAndValueList.Add($"{item.Key}='{item.Value}'");
  73. //}
  74.  
  75. //这是新的代码 2017-5-17 17:00 测试已通过
  76. var NameAndValueList = from item in PropertyNameAndValueDictionary
  77. select $"{item.Key}='{item.Value}'";
  78. string sql = string.Join(",", NameAndValueList);
  79. StringBuilder sqlStatement = new StringBuilder();
  80. sqlStatement.AppendFormat(
  81. $"update {TableName} set {sql} " +
  82. $"where {PrimaryKeyName}='{PrimaryKeyValue}'"
  83. );
  84. return sqlStatement.ToString();
  85. }
  86.  
  87. #endregion
  88.  
  89. #region 获取Deletesql语句 实现IDelete接口
  90. public string DeleteSqlString(object obj)
  91. {
  92. var type = obj.GetType();
  93. var TableName = TypeHelperFactory.GetTableName(type);
  94. var PrimaryKey = TypeHelperFactory.GetPrimaryKey(type);
  95. if (PrimaryKey == null)
  96. {
  97. throw new Exception("不存在主键");
  98. }
  99. var PrimaryKeyValue = TypeHelperFactory.GetPrimaryKeyValue(obj, PrimaryKey);
  100. StringBuilder SqlStatement = new StringBuilder();
  101. SqlStatement.AppendFormat($"delete from {TableName} where {PrimaryKey}='{PrimaryKeyValue}'");
  102. return SqlStatement.ToString();
  103. }
  104.  
  105. #endregion
  106. }

SqlServerSqlStatement.cs

这个类实现了ISqlStatementBuilder这个接口里边定义的方法。其余的两个类只是继承了接口,并没有实现接口定义的具体方法。

接下来这一层的重点来了!

首先这是一个数据库的枚举类

  1. /// <summary>
  2. /// 这是一个枚举类型 用于枚举数据库的类型
  3. /// </summary>
  4. public enum DataBaseType
  5. {
  6. SqlServer = ,
  7. MySql = ,
  8. Oracle =
  9. }

DataBaseType.cs

接下来这是对外提供服务的一个类,我用反射获取枚举过来的数据库的类型字符串,然后通过反射生成对应的实例。(这个东西的详细用法,我的这篇博客里有介绍http://www.cnblogs.com/qulianqing/p/6842829.html

  1. public static class SqlBuilderFactory
  2. {
  3. public static ISqlStatementBuilder GetInstance(DataBaseType DbType)
  4. {
  5. string DataBaseTypeName = Enum.Parse(DbType.GetType(), DbType.ToString()).ToString();
  6. var NamespaceName = "MyEntityFrameWork.SqlBuilderFactorys.Implement";
  7. string InstanceClassName = DataBaseTypeName + "SqlStatement";
  8. return (ISqlStatementBuilder)Assembly.Load(new AssemblyName("MyEntityFrameWork"))
  9. .CreateInstance(NamespaceName+"."+InstanceClassName);
  10. }
  11.  
  12. }

对于外界调用只用这样声明里边参数只用传递对应的数据库的类型。

  1. ISqlStatementBulider SqlBuilder = SqlBuilderFactory.GetInstance(DataBaseType.SqlServer);

这样做的好处是:对于拓展我是支持的,对于外界调用者,他并不知道我是怎么实现的,我用什么方式实现的,以及怎么使用。他只需改变传递的枚举参数就可以了。

如果说以后加入了Access类型的数据库,我只用在枚举类中加入Access的枚举,在实现文件夹中添加AccessSqlStatement.cs这样的一个类,让它实现ISqlSatementBulider接口定义的方法,这样就完成了。这样做我个人感觉拓展很容易。具体是什么设计模式,我也忘了,反正就是这个思想。

接下来我们进入了第三层,也就是目前来说的最高层,也是算是应用层。

这一层是 一个数据库工厂,用于执行sql语句。调用sql语句的工厂

这是这一层的结构,首先是一个基类文件夹,一个实现文件夹,一个接口文件夹(目前为空尚未使用)

在基类文件夹中声明了一个抽象类BasicsDatabase.cs这是一个基类,定义了需要实现的方法。(我仿照着.net core 下的asp.net mvc 项目里的StartUp.cs的构造函数,实现了一个我自己用的一个构造函数。读取json配置文件必须用的一个IConfigurationRoot )

  1. public abstract class BasicsDatabase
  2. {
  3. protected ISqlStatementBuilder SqlBuilder { get; set; }
  4. protected IDbConnection Connection { get; set; }
  5. public IConfigurationRoot Configuration { get; }
  6. protected IDbCommand Command { get; set; }
  7. protected BasicsDatabase()
  8. {
  9. var builder = new ConfigurationBuilder()
  10. .SetBasePath(Directory.GetCurrentDirectory())
  11. .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
  12. Configuration = builder.Build();
  13. }
  14.  
  15. protected abstract string DatabaseConncetionString();
  16. public abstract List<T> GetAllInfo<T>() where T : new();
  17. public abstract bool Add(object data);
  18. public abstract bool Update(object data);
  19. public abstract bool Remove(object data);
  20. }

BasicsDatabase.cs

接下来是实现文件夹

分别实现了三种不同的数据库,我这里只是实现了SqlServer的数据库类型。其他两个只是演示了怎么使用,以及怎么实现。

  1. public class SqlServerDatabase : BasicsDatabase
  2. {
  3. public SqlServerDatabase() : base()
  4. {
  5. base.Connection = new SqlConnection(DatabaseConncetionString());
  6. Connection.Open();
  7. base.Command = new SqlCommand();
  8. Command.Connection = base.Connection;
  9. //这里重要
  10. base.SqlBuilder = SqlBuilderFactory.GetInstance(DataBaseType.SqlServer);
  11. }
  12.  
  13. public override List<T> GetAllInfo<T>()
  14. {
  15. Command.CommandText = SqlBuilder.ReadSqlString(new T());
  16. var Result = Command.ExecuteReader(CommandBehavior.SingleResult);
  17. var AllInfoList = new List<T>();
  18. while (Result.Read())
  19. {
  20. var Record = (IDataRecord)Result;
  21. AddOneObjectToList(ref AllInfoList, Record);
  22. }
  23.  
  24. Result.Dispose();
  25. return AllInfoList;
  26. }
  27.  
  28. private void AddOneObjectToList<T>(ref List<T> objectList, IDataRecord record) where T : new()
  29. {
  30. //获取所有的特性名称
  31. //查找record中的字段名称是否相同
  32. //如果相同将其值赋给该字段
  33. var PropertyNames = TypeHelperFactory.GetAllPropertyList(typeof(T));
  34. var Obj = new T();
  35. for (int i = ; i < record.FieldCount; i++)
  36. {
  37. var PropertyName = PropertyNames.FirstOrDefault(name => name == record.GetName(i));
  38. if (PropertyName != null)
  39. {
  40. TypeHelperFactory.SetPropertyValue(Obj, PropertyName, record[i]);
  41. }
  42.  
  43. }
  44. objectList.Add(Obj);
  45. }
  46. public override bool Add(object data)
  47. {
  48. Command.CommandText = SqlBuilder.CreateSqlString(data);
  49. return Command.ExecuteNonQuery() > ;
  50. }
  51. public override bool Remove(object data)
  52. {
  53. Command.CommandText = SqlBuilder.DeleteSqlString(data);
  54. return Command.ExecuteNonQuery() > ;
  55. }
  56.  
  57. public override bool Update(object data)
  58. {
  59. Command.CommandText = SqlBuilder.UpdateSqlString(data);
  60. return Command.ExecuteNonQuery() > ;
  61. }
  62.  
  63. protected override string DatabaseConncetionString()
  64. {
  65. return base.Configuration.GetConnectionString("DataContext");
  66. }
  67.  
  68. }

SqlServerDatabase.cs

重点代码已经在注释中标注。这里给大家提一个醒在 24行的代码出,如果用.close()这个方法的话,add,和Update方法都没有问题,但是在Delete方法执行的时候会抛IDataReader没有关闭,请关闭后再使用的异常,用.dispose()这个方法可以解决。这是微软官网给的IDataReader样例https://docs.microsoft.com/en-us/dotnet/api/system.data.idatareader?view=netcore-1.1他用的是Close()这个方法,我刚开始也是用的是close(),这个方法,后来找了好久,改为dispose()就好了,具体原因还没有深入了解。

这是其余两个只是演示了怎么使用

  1. public class MySqlDataBase : BasicsDatabase
  2. {
  3. /// <summary>
  4. /// 这是MySql数据库的实现方式
  5. /// 只用于演示并没有实现功能
  6. /// 时间:2017-5-12
  7. /// Author:曲
  8. /// </summary>
  9. public MySqlDataBase() : base()
  10. {
  11. base.Connection = new MySqlConnection();
  12. base.Connection.Open();
  13. base.Command = new MySqlCommand();
  14. base.Command.Connection = base.Connection;
  15. base.SqlBuilder = SqlBuilderFactory.GetInstance(DataBaseType.MySql);
  16. }
  17. public override bool Add(object data)
  18. {
  19. base.Command.CommandText = SqlBuilder.CreateSqlString(data);
  20. return base.Command.ExecuteNonQuery() > ;
  21. }
  22.  
  23. public override List<T> GetAllInfo<T>()
  24. {
  25. throw new NotImplementedException();
  26. }
  27.  
  28. public override bool Remove(object data)
  29. {
  30. throw new NotImplementedException();
  31. }
  32.  
  33. public override bool Update(object data)
  34. {
  35. throw new NotImplementedException();
  36. }
  37.  
  38. protected override string DatabaseConncetionString()
  39. {
  40. throw new NotImplementedException();
  41. }
  42. }

MySqlDataBase.cs

  1. /// <summary>
  2. /// Oracle数据库的实现方式
  3. /// 这是只是用于演示并没有真正实现
  4. /// 时间:2017-5-12
  5. /// Author:曲
  6. /// </summary>
  7. public class OracleDataBase : BasicsDatabase
  8. {
  9.  
  10. public OracleDataBase() : base()
  11. {
  12. //base.Connection = new OracleConnection(DatabaseConncetionString());
  13. //Connection.Open();
  14. //base.Command = new OracleCommmand();
  15. //Command.Connection = Connection;
  16. //base.SqlBuilder = SqlBuilderFactory.GetInstance(DataBaseType.Oracle);
  17. }
  18. public override bool Add(object data)
  19. {
  20. Command.CommandText = SqlBuilder.CreateSqlString(data);
  21. return Command.ExecuteNonQuery() > ;
  22. }
  23.  
  24. public override List<T> GetAllInfo<T>()
  25. {
  26. throw new NotImplementedException();
  27. }
  28.  
  29. public override bool Remove(object data)
  30. {
  31. throw new NotImplementedException();
  32. }
  33.  
  34. public override bool Update(object data)
  35. {
  36. throw new NotImplementedException();
  37. }
  38.  
  39. protected override string DatabaseConncetionString()
  40. {
  41. throw new NotImplementedException();
  42. }
  43. }

OracleDataBase.cs

这里还是挺丑的毕竟每个子类都要知道具体的实现步骤,准备把子类构造函数里的构造过程,放到抽象类中去,不知道能不能行的通,待明天尝试

到了这里我的EF框架大致就模拟成功了,可以实现CRUD到数据库中。

关于使用,我写了一个  使用说明.md文件。上边有配置步骤,可以一步步的配置然后就可以使用了。

配置我自己定义的服务(这里实现的是sqlServer类型的数据库,如果实现了其他类型的,在这里改动一下就行了)

  1. //添加我自己的服务,这里声明的类型为基类型性,实现的是sqlServer的的数据库的类型。
  2. services.AddScoped<BasicsDatabase, SqlServerDatabase>();

我在core环境下建了一个mvc项目

在views文件夹中添加一个UserInfo文件夹

里边有这么几个文件和用EF框架生成的一样,不过这里要进行手工的写,

在Controller文件夹中添加一个mvc控制器 在控制器中是是这么用的

  1. using Microsoft.AspNetCore.Mvc;
  2. using MyEntityFrameWork.DateBaseFactory.BaseClass;
  3. using System;
  4. using System.Linq;
  5. using TestMyEntityFramework.Models;
  6.  
  7. // For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
  8.  
  9. namespace TestMyEntityFramework.Controllers
  10. {
  11. public class UserInfoController : Controller
  12. {
  13. private readonly BasicsDatabase _context;
  14. public UserInfoController(BasicsDatabase Database)
  15. {
  16. _context = Database;
  17. }
  18.  
  19. // GET: /<controller>/
  20. public IActionResult Index()
  21. {
  22.  
  23. return View(_context.GetAllInfo<Users>());
  24. }
  25. public IActionResult Create()
  26. {
  27. return View();
  28. }
  29. [HttpPost]
  30. [ValidateAntiForgeryToken]
  31. public IActionResult Create([Bind("ID,Name,pwd")] Users userInfo)
  32. {
  33. if (ModelState.IsValid)
  34. {
  35. _context.Add(userInfo);
  36. return RedirectToAction("Index");
  37. }
  38. return View(userInfo);
  39. }
  40. public IActionResult Edit(int? id)
  41. {
  42. if (id == null)
  43. {
  44. return NotFound();
  45. }
  46.  
  47. var userInfo = _context.GetAllInfo<Users>().FirstOrDefault(u=>u.ID==id);
  48. if (userInfo == null)
  49. {
  50. return NotFound();
  51. }
  52. return View(userInfo);
  53. }
  54.  
  55. [HttpPost]
  56. [ValidateAntiForgeryToken]
  57. public IActionResult Edit(int id, [Bind("ID,Name,pwd")] Users userInfo)
  58. {
  59. if (id != userInfo.ID)
  60. {
  61. return NotFound();
  62. }
  63.  
  64. if (ModelState.IsValid)
  65. {
  66. try
  67. {
  68. _context.Update(userInfo);
  69.  
  70. }
  71. catch
  72. {
  73. if (!UserInfoExists(userInfo.ID))
  74. {
  75. return NotFound();
  76. }
  77. else
  78. {
  79. throw new Exception("数据更新失败");
  80. }
  81. }
  82. return RedirectToAction("Index");
  83. }
  84. return View(userInfo);
  85. }
  86.  
  87. public IActionResult Delete(int? id)
  88. {
  89. if (id == null)
  90. {
  91. return NotFound();
  92. }
  93.  
  94. var userInfo = _context.GetAllInfo<Users>()
  95. .SingleOrDefault(m => m.ID == id);
  96. if (userInfo == null)
  97. {
  98. return NotFound();
  99. }
  100.  
  101. return View(userInfo);
  102. }
  103.  
  104. [HttpPost, ActionName("Delete")]
  105. [ValidateAntiForgeryToken]
  106. public IActionResult DeleteConfirmed(int id)
  107. {
  108. var userInfo = _context.GetAllInfo<Users>().SingleOrDefault(m => m.ID == id);
  109.  
  110. _context.Remove(userInfo);
  111. return RedirectToAction("Index");
  112. }
  113.  
  114. public IActionResult Details(int? id)
  115. {
  116. if (id == null)
  117. {
  118. return NotFound();
  119. }
  120.  
  121. var userInfo = _context.GetAllInfo<Users>()
  122. .SingleOrDefault(m => m.ID == id);
  123. if (userInfo == null)
  124. {
  125. return NotFound();
  126. }
  127.  
  128. return View(userInfo);
  129. }
  130. private bool UserInfoExists(int id)
  131. {
  132. return _context.GetAllInfo<Users>().Any(e => e.ID == id);
  133. }
  134. }
  135. }

UserInfoController.cs

是不是和EF挺像的,就是GetAllList<T>这个方法有点丑,待我想到好方法,再改进一下,据说EF不是用反射,用的是泛型,我今天大致看了一下源码,确实是这样的,挺好的应该,毕竟反射对性能损失是较大的。

待我研究出来头绪了,再和大家分享。

git地址:https://github.com/1483523635/MyEntityFramework

测试的Git地址:https://github.com/1483523635/UseMyEntityFrameWork

自己实现的一个简单的EF框架(反射实现)的更多相关文章

  1. Core1.1环境下,自己实现的一个简单的CRUD框架(反射实现)

    我实现了一个简单的EF框架,主要用于操纵数据库.实现了对数据库的基本操纵--CRUD 这是项目结构 这是一个 core 下的 DLL 写了一个数据库工厂,用于执行sql语句.调用sql语句工厂 写了一 ...

  2. 用Python写一个简单的Web框架

    一.概述 二.从demo_app开始 三.WSGI中的application 四.区分URL 五.重构 1.正则匹配URL 2.DRY 3.抽象出框架 六.参考 一.概述 在Python中,WSGI( ...

  3. 一个简单的web框架实现

    一个简单的web框架实现 #!/usr/bin/env python # -- coding: utf-8 -- __author__ = 'EchoRep' from wsgiref.simple_ ...

  4. koa2源码解读及实现一个简单的koa2框架

    阅读目录 一:封装node http server. 创建koa类构造函数. 二:构造request.response.及 context 对象. 三:中间件机制的实现. 四:错误捕获和错误处理. k ...

  5. 如何实现一个简单的MVVM框架

    接触过web开发的同学想必都接触过MVVM,业界著名的MVVM框架就有AngelaJS.今天闲来无事,决定自己实现一个简单的MVVM框架玩一玩.所谓简单,就是仅仅实现一个骨架,仅表其意,不摹其形. 分 ...

  6. 动手造轮子:实现一个简单的 AOP 框架

    动手造轮子:实现一个简单的 AOP 框架 Intro 最近实现了一个 AOP 框架 -- FluentAspects,API 基本稳定了,写篇文章分享一下这个 AOP 框架的设计. 整体设计 概览 I ...

  7. 徒手撸一个简单的RPC框架

    来源:https://juejin.im/post/5c4481a4f265da613438aec3 之前在牛逼哄哄的 RPC 框架,底层到底什么原理得知了RPC(远程过程调用)简单来说就是调用远程的 ...

  8. 动手写一个简单的Web框架(模板渲染)

    动手写一个简单的Web框架(模板渲染) 在百度上搜索jinja2,显示的大部分内容都是jinja2的渲染语法,这个不是Web框架需要做的事,最终,居然在Werkzeug的官方文档里找到模板渲染的代码. ...

  9. 动手写一个简单的Web框架(Werkzeug路由问题)

    动手写一个简单的Web框架(Werkzeug路由问题) 继承上一篇博客,实现了HelloWorld,但是这并不是一个Web框架,只是自己手写的一个程序,别人是无法通过自己定义路由和返回文本,来使用的, ...

随机推荐

  1. OOP的完美点缀—AOP之SpringAOP实现原理

    OOP的完美点缀-AOP之SpringAOP实现原理 前言 OOP与AOP OOP(Object Oriented Programming,面向对象编程),通过封装.继承将程序抽象为各个层次的对象,进 ...

  2. Python之路-字符编码&数据类型补充

    作业 三级菜单程序 menu = { '北京':{ '海淀':{ '五道口':{ 'soho':{ }, '网易':{ }, 'google':{ } }, '中关村':{ '爱奇艺':{}, '汽车 ...

  3. 转接口IC GM7122:BT656转CVBS芯片 视频编码电路

    1 概述    视频编码电路主要实现接收8位CCIR656格式的YUV数据,(例如MPEG解码数据),并编码成CVBS信号,经过D/A转换后输出.基本的编码功能包括副载波产生,色差信号调制,同步信号内 ...

  4. 【微信开发】PHP中奖概率经典算法实例

    $arr=array("50","30","20"); //这里简单列出三个数 $pro = array_sum($arr); // 概率数 ...

  5. 聊天界面使用IQKeyboardManager导航栏及整个页面上移的解决方法

    问题: 使用第三方库IQKeyboardManager时会使整个页面上移,导航栏页偏移出了显示范围.在聊天界面就会使得上面的消息看不到. 解决方法: 首先说明:在聊天界面使用IQKeyboardMan ...

  6. css 实现旋转八卦图

    虽然这不算什么亮点,不过也可以供路上的小伙伴学习下 直接上干货: <!doctype html> <html lang="en"> <head> ...

  7. ios 检测屏幕方向

    方法一:通知中心监听 name: // UIDeviceOrientationDidChangeNotification   允许方向改变的情况下,监听设备方向,与电池条无关 // UIApplica ...

  8. vue项目目录介绍

    Vue项目目录 初始化项目 vue init webpack []projectname] cd [projectname] npm install vue run dev 目录树 +---build ...

  9. Java集合的区别和选择

              Collection |--List       有序,可重复 |--ArrayList 底层数据结构是数组,查询快,增删慢. 线程不安全,效率高 |--Vector 底层数据结构 ...

  10. DirectFB学习笔记三

    本篇目的,通过键盘的esc键控制程序退出.学习输入设备产生事件,接收事件,产生反应. 首先获取输入设备 IDirectFBInputDevice *keyboard = NULL; dfb->G ...