EF架构~过滤导航属性等,拼接SQL字符串

拼接T—SQL串,并使它具有通用性

好处:与服务器建立一次连接,给服务器发一条SQL命令,即可实现

代码如下:

 1   /// <summary>
 2         /// 构建Insert语句串
 3         /// 主键为自增时,如果主键值为0,我们将主键插入到SQL串中
 4         /// </summary>
 5         /// <typeparam name="TEntity"></typeparam>
 6         /// <param name="entity"></param>
 7         /// <returns></returns>
 8         private Tuple<string, object[]> CreateInsertSQL<TEntity>(TEntity entity) where TEntity : class
 9         {
10             if (entity == null)
11                 throw new ArgumentException("The database entity can not be null.");
12
13             Type entityType = entity.GetType();
14             var table = entityType.GetProperties().Where(i => i.PropertyType != typeof(EntityKey)
15                && i.PropertyType != typeof(EntityState)
16                && i.GetValue(entity, null) != null
17                && (i.PropertyType.IsValueType || i.PropertyType == typeof(string)))
18                .ToArray();//过滤主键,航行属性,状态属性等
19             List<string> pkList = GetPrimaryKey<TEntity>().Select(i => i.Name).ToList();
20
21             List<object> arguments = new List<object>();
22             StringBuilder fieldbuilder = new StringBuilder();
23             StringBuilder valuebuilder = new StringBuilder();
24
25             fieldbuilder.Append(" INSERT INTO " + string.Format("[{0}]", entityType.Name) + " (");
26
27             foreach (var member in table)
28             {
29                 if (pkList.Contains(member.Name) && Convert.ToString(member.GetValue(entity, null)) == "0")
30                     continue;
31                 object value = member.GetValue(entity, null);
32                 if (value != null)
33                 {
34                     if (arguments.Count != 0)
35                     {
36                         fieldbuilder.Append(", ");
37                         valuebuilder.Append(", ");
38                     }
39
40                     fieldbuilder.Append(member.Name);
41                     if (member.PropertyType == typeof(string) || member.PropertyType == typeof(DateTime))
42                         valuebuilder.Append("‘{" + arguments.Count + "}‘");
43                     else
44                         valuebuilder.Append("{" + arguments.Count + "}");
45                     if (value.GetType() == typeof(string))
46                         value = value.ToString().Replace("‘", "char(39)");
47                     arguments.Add(value);
48
49                 }
50             }
51
52
53             fieldbuilder.Append(") Values (");
54
55             fieldbuilder.Append(valuebuilder.ToString());
56             fieldbuilder.Append(");");
57             return new Tuple<string, object[]>(fieldbuilder.ToString(), arguments.ToArray());
58         }

对于EF架构中的批量更新操作,需要我们为实体的导航属性进行手动的标示,因为EF生成的实体中没有一个特殊的说明,所以,我们必须要告诉系统,哪个属性是导航属性,而导航属性是我们不去进行update的。

1    /// <summary>
2     /// 属性的导航属性
3     /// </summary>
4     public class NavigationAttribute : Attribute
5     {
6
7     }

而对于要进行批量更新的实体,我们需要为导航属性添加这个特性

1    public class User
2     {
3         public int UserID { get; set; }
4         [Navigation]
5         public User_Extension User_Extension { get; set; }
6     }

而对于我们构建批量Update语句,请看代码,它需要对导航属性进行过滤

 1         /// <summary>
 2         /// 构建Update语句串
 3         /// </summary>
 4         /// <typeparam name="TEntity"></typeparam>
 5         /// <param name="entity"></param>
 6         /// <returns></returns>
 7         private Tuple<string, object[]> CreateUpdateSQL<TEntity>(TEntity entity) where TEntity : class
 8         {
 9             if (entity == null)
10                 throw new ArgumentException("The database entity can not be null.");
11             List<string> pkList = GetPrimaryKey<TEntity>().Select(i => i.Name).ToList();
12
13             Type entityType = entity.GetType();
14             var table = entityType.GetProperties().Where(i =>
15                 !pkList.Contains(i.Name)
16                 && i.GetValue(entity, null) != null
17                 && i.PropertyType != typeof(EntityState)
18                 && !(i.GetCustomAttributes(false).Length > 0
19                 && i.GetCustomAttributes(false).Where(j => j.GetType() == typeof(NavigationAttribute)) != null)
20                 && (i.PropertyType.IsValueType || i.PropertyType == typeof(string)) //过滤导航属性
21                  ).ToArray();
22
23             //过滤主键,航行属性,状态属性等
24             if (pkList == null || pkList.Count == 0)
25                 throw new ArgumentException("The Table entity have not a primary key.");
26             List<object> arguments = new List<object>();
27             StringBuilder builder = new StringBuilder();
28
29             foreach (var change in table)
30             {
31                 if (pkList.Contains(change.Name))
32                     continue;
33                 if (arguments.Count != 0)
34                     builder.Append(", ");
35                 builder.Append(change.Name + " = {" + arguments.Count + "}");
36                 if (change.PropertyType == typeof(string) || change.PropertyType == typeof(DateTime))
37                     arguments.Add("‘" + change.GetValue(entity, null).ToString().Replace("‘", "char(39)") + "‘");
38                 else
39                     arguments.Add(change.GetValue(entity, null));
40             }
41
42             if (builder.Length == 0)
43                 throw new Exception("没有任何属性进行更新");
44
45             builder.Insert(0, " UPDATE " + string.Format("[{0}]", entityType.Name) + " SET ");
46
47             builder.Append(" WHERE ");
48             bool firstPrimaryKey = true;
49
50             foreach (var primaryField in pkList)
51             {
52                 if (firstPrimaryKey)
53                     firstPrimaryKey = false;
54                 else
55                     builder.Append(" AND ");
56
57                 object val = entityType.GetProperty(primaryField).GetValue(entity, null);
58                 builder.Append(GetEqualStatment(primaryField, arguments.Count));
59                 arguments.Add(val);
60             }
61             return new Tuple<string, object[]>(builder.ToString(), arguments.ToArray());
62
63         }

而对子类公开的Update方法,我们进行了一个封装,它通过操作枚举来确实你是要insert,update还是delete,看代码

 1         /// <summary>
 2         /// 执行SQL,根据SQL操作的类型
 3         /// </summary>
 4         /// <typeparam name="TEntity"></typeparam>
 5         /// <param name="list"></param>
 6         /// <param name="sqlType"></param>
 7         /// <returns></returns>
 8         protected string DoSQL<TEntity>(IEnumerable<TEntity> list, SQLType sqlType) where TEntity : class
 9         {
10             StringBuilder sqlstr = new StringBuilder();
11             switch (sqlType)
12             {
13                 case SQLType.Insert:
14                     list.ToList().ForEach(i =>
15                     {
16                         Tuple<string, object[]> sql = CreateInsertSQL(i);
17                         sqlstr.AppendFormat(sql.Item1, sql.Item2);
18                     });
19                     break;
20                 case SQLType.Update:
21                     list.ToList().ForEach(i =>
22                     {
23                         Tuple<string, object[]> sql = CreateUpdateSQL(i);
24                         sqlstr.AppendFormat(sql.Item1, sql.Item2);
25                     });
26                     break;
27                 case SQLType.Delete:
28                     list.ToList().ForEach(i =>
29                     {
30                         Tuple<string, object[]> sql = CreateDeleteSQL(i);
31                         sqlstr.AppendFormat(sql.Item1, sql.Item2);
32                     });
33                     break;
34                 default:
35                     throw new ArgumentException("请输入正确的参数");
36             }
37             return sqlstr.ToString();
38         }

时间: 2024-10-09 01:48:53

EF架构~过滤导航属性等,拼接SQL字符串的相关文章

【批量加入】-拼接sql字符串

如今做的一个项目须要用到批量加入,可是封装的底层没有这种方法,所以自食其力,自己来写.我们用的是拼接sql字符串的方法来实现功能. 详细实现流程:首先将须要的数据存储到实体的list中,然后将这个list传给我们批量加入的方法.批量加入的方法首先应该打开数据库连接,然后開始进行sql字符串的拼接,拼接完毕后.调用sqlhelper方法进行加入. 详细代码例如以下: #region 批量加入实体 /// <summary> /// 批量加入实体 /// </summary> ///

【批量添加】-拼接sql字符串

现在做的一个项目需要用到批量添加,但是封装的底层没有这个方法,所以自食其力,自己来写.我们用的是拼接sql字符串的方法来实现功能. 具体实现流程:首先将需要的数据存储到实体的list中,然后将这个list传给我们批量添加的方法.批量添加的方法首先应该打开数据库连接,然后开始进行sql字符串的拼接,拼接完成后,调用sqlhelper方法进行添加. 具体代码如下: #region 批量添加实体 /// <summary> /// 批量添加实体 /// </summary> /// &l

EF Code First 导航属性 与外键

一对多关系 项目中最常用到的就是一对多关系了.Code First对一对多关系也有着很好的支持.很多情况下我们都不需要特意的去配置,Code First就能通过一些引用属性.导航属性等检测到模型之间的关系,自动为我们生成外键.观察下面的类: public class Destination { public int DestinationId { get; set; } public string Name { get; set; } public string Country { get; s

Excel 2013拼接Sql字符串

在做开发的过程中,经常需要根据Excel中的数据去数据库查询,少量数据还可以去复制粘贴,大量数据时就需要将Excel中的数据拼接成自己需要的Sql,以提升工作效率. 场景1:将某一列拼接成Sql中的In条件 假设现在有如下的Excel数据,我需要从数据库中查询出这些门店的数据 操作方法如下图所示: 将生成的一列数据复制到Visual Studito Code中,进行替换即可 场景2:将某一列拼接成C#中的List 假设现在有如下的Excel数据,我需要将这些值写在C#中的List<string>

MySQL中limit使用动态参数的解决方法(拼接SQL字符串语句来执行SQL)

官方好像说过limit已经在5.6版本上支持了动态参数,但是测试时依然还是不行. 那么要解决limit动态参数唯一能做的就是使用字符串SQL拼接的形式,然后再进行执行. 一般有以下方式解决: 1.存储过程拼接 2.函数拼接 3.视图里拼接 4.当前查询的session中使用 其实上面都是同一个意思,就是使用一个变量存取这个SQL,然后再执行这个变量. 样例: set @stmt = concat('select * from ',table_name,' limit ?,?'); prepare

EF架构~基于EF数据层的实现

回到目录 之前写过关于实现一个完整的EF架构的文章,文章的阅读量也是满大的,自己很欣慰,但是,那篇文章是我2011年写的,所以,技术有些不成熟,所以今天把我的2014年写的EF底层架构公开一下,这个架构比2011年的有了很大程度的提高,主要在接口规范,查询规范上,并引入了排序功能,两步对完善了EF对数据的批量操作,可以说,这次的架构是很有看点的. 一 一个基础操作接口 /// <summary> /// 基础的数据操作规范 /// 与ORM架构无关 /// </summary> /

java用字符串拼接SQL语句的特殊字符转义问题

在实际的项目开发中,往往会根据用户在界面的文本框中输入的信息,去数据库中做模糊查询.如果使用的是原始的JDBC和SQL,往往需要对用户的输入进行转义,避免生成的sql语法错误,或者防止SQL注入.比如对输入的%和_和',就需要进行转义,因为这3个字符是SQL的特殊字符,如果不处理会导致sql出错或者是查询数据不正确. 假如有这样1个查询请求,模糊查询标题中包含a%b_cc'd的记录,正确的sql应该是下面这样的: select * from t_sch_work_info t where t.t

重构之路 组合查询之传递SQL字符串

既然是使用VB.NET语言对机房收费系统进行重构,那么无可避免的要去解决组合查询的问题,在VB版的实现中这是一个难点,不过大家还是依靠自己或者共同的智慧解决了这个看似复杂的问题. 如今编程的语言不同是一方面,更重要的是系统的结构不一样了,采用了三层架构去实现系统,这样一来就要考虑组合查询的在三层结构中的实现方法.当然,组合查询的核心办法是不变的,都是通过将查询的各个条件组装成SQL查询语句的where子句来实现的,问题就是这个where子句的组装在哪里完成? 如果放在U层完成,那么我们向下传递的

MVC3+EF4.1学习系列(五)----- EF查找导航属性的几种方式

通过上一篇的学习 我们把demo的各种关系终于搭建里起来 以及处理好了如何映射到数据库等问题 但是 只是搭建好了关系 问题还远没有解决 这篇就来写如何查找导航属性 和查找导航属性的几种方式 已经跟踪生成的SQL来检测是否满意 通过这节学习 来明白什么时候用哪个~~ 一.三种加载 1.延迟加载 这是原文中的图 大家可以去看下  我模仿上面的做了个测试  出现了  已有打开的与此 Command 相关联的 DataReader,必须首先将它关闭. 我的解决办法是    var departments