(转)EntityFramework.Extensions
using System;using System.Collections.Generic;using System.Data;using System.Data.Common;using System.Data.Common.CommandTrees;using System.Data.Entity;using System.Data.EntityClient;using System.Data.Metadata.Edm;using System.Data.Objects.DataClasses;using System.Data.SqlClient;using System.Linq;using System.Linq.Dynamic;using System.Linq.Expressions;using System.Reflection;using System.Text;using System.Data.Objects;using EntityFramework.Mapping;using EntityFramework.Reflection;namespace EntityFramework.Extensions{ /// <summary> /// An extensions class for batch queries. /// </summary> public static class BatchExtensions { /// <summary> /// Executes a delete statement using the query to filter the rows to be deleted. /// </summary> /// <typeparam name="TEntity">The type of the entity.</typeparam> /// <param name="source">The source used to determine the table to delete from.</param> /// <param name="query">The IQueryable used to generate the where clause for the delete statement.</param> /// <returns>The number of row deleted.</returns> /// <remarks> /// When executing this method, the statement is immediately executed on the database provider /// and is not part of the change tracking system. Also, changes will not be reflected on /// any entities that have already been materialized in the current context. /// </remarks> public static int Delete<TEntity>( this ObjectSet<TEntity> source, IQueryable<TEntity> query) where TEntity : class { if (source == null) throw new ArgumentNullException("source"); if (query == null) throw new ArgumentNullException("query"); ObjectContext objectContext = source.Context; if (objectContext == null) throw new ArgumentException("The ObjectContext for the source query can not be null.", "source"); EntityMap entityMap = source.GetEntityMap<TEntity>(); if (entityMap == null) throw new ArgumentException("Could not load the entity mapping information for the source ObjectSet.", "source"); ObjectQuery<TEntity> objectQuery = query.ToObjectQuery(); if (objectQuery == null) throw new ArgumentException("The query must be of type ObjectQuery or DbQuery.", "query"); return Delete(objectContext, entityMap, objectQuery); } /// <summary> /// Executes a delete statement using an expression to filter the rows to be deleted. /// </summary> /// <typeparam name="TEntity">The type of the entity.</typeparam> /// <param name="source">The source used to determine the table to delete from.</param> /// <param name="filterExpression">The filter expression used to generate the where clause for the delete statement.</param> /// <returns>The number of row deleted.</returns> /// <example>Delete all users with email domain @test.com. /// <code><![CDATA[ /// var db = new TrackerEntities(); /// string emailDomain = "@test.com"; /// int count = db.Users.Delete(u => u.Email.EndsWith(emailDomain)); /// ]]></code> /// </example> /// <remarks> /// When executing this method, the statement is immediately executed on the database provider /// and is not part of the change tracking system. Also, changes will not be reflected on /// any entities that have already been materialized in the current context. /// </remarks> public static int Delete<TEntity>( this ObjectSet<TEntity> source, Expression<Func<TEntity, bool>> filterExpression) where TEntity : class { if (source == null) throw new ArgumentNullException("source"); if (filterExpression == null) throw new ArgumentNullException("filterExpression"); return source.Delete(source.Where(filterExpression)); } /// <summary> /// Executes a delete statement using the query to filter the rows to be deleted. /// </summary> /// <typeparam name="TEntity">The type of the entity.</typeparam> /// <param name="source">The source used to determine the table to delete from.</param> /// <param name="query">The IQueryable used to generate the where clause for the delete statement.</param> /// <returns>The number of row deleted.</returns> /// <remarks> /// When executing this method, the statement is immediately executed on the database provider /// and is not part of the change tracking system. Also, changes will not be reflected on /// any entities that have already been materialized in the current context. /// </remarks> public static int Delete<TEntity>( this DbSet<TEntity> source, IQueryable<TEntity> query) where TEntity : class { if (source == null) throw new ArgumentNullException("source"); if (query == null) throw new ArgumentNullException("query"); ObjectQuery<TEntity> sourceQuery = source.ToObjectQuery(); if (sourceQuery == null) throw new ArgumentException("The query must be of type ObjectQuery or DbQuery.", "source"); ObjectContext objectContext = sourceQuery.Context; if (objectContext == null) throw new ArgumentException("The ObjectContext for the source query can not be null.", "source"); EntityMap entityMap = sourceQuery.GetEntityMap<TEntity>(); if (entityMap == null) throw new ArgumentException("Could not load the entity mapping information for the source ObjectSet.", "source"); ObjectQuery<TEntity> objectQuery = query.ToObjectQuery(); if (objectQuery == null) throw new ArgumentException("The query must be of type ObjectQuery or DbQuery.", "query"); return Delete(objectContext, entityMap, objectQuery); } /// <summary> /// Executes a delete statement using an expression to filter the rows to be deleted. /// </summary> /// <typeparam name="TEntity">The type of the entity.</typeparam> /// <param name="source">The source used to determine the table to delete from.</param> /// <param name="filterExpression">The filter expression used to generate the where clause for the delete statement.</param> /// <returns>The number of row deleted.</returns> /// <example>Delete all users with email domain @test.com. /// <code><![CDATA[ /// var db = new TrackerContext(); /// string emailDomain = "@test.com"; /// int count = db.Users.Delete(u => u.Email.EndsWith(emailDomain)); /// ]]></code> /// </example> /// <remarks> /// When executing this method, the statement is immediately executed on the database provider /// and is not part of the change tracking system. Also, changes will not be reflected on /// any entities that have already been materialized in the current context. /// </remarks> public static int Delete<TEntity>( this DbSet<TEntity> source, Expression<Func<TEntity, bool>> filterExpression) where TEntity : class { if (source == null) throw new ArgumentNullException("source"); if (filterExpression == null) throw new ArgumentNullException("filterExpression"); return source.Delete(source.Where(filterExpression)); } /// <summary> /// Executes an update statement using the query to filter the rows to be updated. /// </summary> /// <typeparam name="TEntity">The type of the entity.</typeparam> /// <param name="source">The source used to determine the table to update.</param> /// <param name="query">The query used to generate the where clause.</param> /// <param name="updateExpression">The MemberInitExpression used to indicate what is updated.</param> /// <returns>The number of row updated.</returns> /// <remarks> /// When executing this method, the statement is immediately executed on the database provider /// and is not part of the change tracking system. Also, changes will not be reflected on /// any entities that have already been materialized in the current context. /// </remarks> public static int Update<TEntity>( this ObjectSet<TEntity> source, IQueryable<TEntity> query, Expression<Func<TEntity, TEntity>> updateExpression) where TEntity : class { if (source == null) throw new ArgumentNullException("source"); if (query == null) throw new ArgumentNullException("query"); if (updateExpression == null) throw new ArgumentNullException("updateExpression"); ObjectContext objectContext = source.Context; if (objectContext == null) throw new ArgumentException("The ObjectContext for the source query can not be null.", "source"); EntityMap entityMap = source.GetEntityMap<TEntity>(); if (entityMap == null) throw new ArgumentException("Could not load the entity mapping information for the source ObjectSet.", "source"); ObjectQuery<TEntity> objectQuery = query.ToObjectQuery(); if (objectQuery == null) throw new ArgumentException("The query must be of type ObjectQuery or DbQuery.", "query"); return Update(objectContext, entityMap, objectQuery, updateExpression); } /// <summary> /// Executes an update statement using an expression to filter the rows that are updated. /// </summary> /// <typeparam name="TEntity">The type of the entity.</typeparam> /// <param name="source">The source used to determine the table to update.</param> /// <param name="filterExpression">The filter expression used to generate the where clause.</param> /// <param name="updateExpression">The MemberInitExpression used to indicate what is updated.</param> /// <returns>The number of row updated.</returns> /// <example>Update all users in the test.com domain to be inactive. /// <code><![CDATA[ /// var db = new TrackerEntities(); /// string emailDomain = "@test.com"; /// int count = db.Users.Update( /// u => u.Email.EndsWith(emailDomain), /// u => new User { IsApproved = false, LastActivityDate = DateTime.Now }); /// ]]></code> /// </example> /// <remarks> /// When executing this method, the statement is immediately executed on the database provider /// and is not part of the change tracking system. Also, changes will not be reflected on /// any entities that have already been materialized in the current context. /// </remarks> public static int Update<TEntity>( this ObjectSet<TEntity> source, Expression<Func<TEntity, bool>> filterExpression, Expression<Func<TEntity, TEntity>> updateExpression) where TEntity : class { if (source == null) throw new ArgumentNullException("source"); if (filterExpression == null) throw new ArgumentNullException("filterExpression"); return source.Update(source.Where(filterExpression), updateExpression); } /// <summary> /// Executes an update statement using the query to filter the rows to be updated. /// </summary> /// <typeparam name="TEntity">The type of the entity.</typeparam> /// <param name="source">The source used to determine the table to update.</param> /// <param name="query">The query used to generate the where clause.</param> /// <param name="updateExpression">The MemberInitExpression used to indicate what is updated.</param> /// <returns>The number of row updated.</returns> /// <remarks> /// When executing this method, the statement is immediately executed on the database provider /// and is not part of the change tracking system. Also, changes will not be reflected on /// any entities that have already been materialized in the current context. /// </remarks> public static int Update<TEntity>( this DbSet<TEntity> source, IQueryable<TEntity> query, Expression<Func<TEntity, TEntity>> updateExpression) where TEntity : class { if (source == null) throw new ArgumentNullException("source"); if (query == null) throw new ArgumentNullException("query"); if (updateExpression == null) throw new ArgumentNullException("updateExpression"); ObjectQuery<TEntity> sourceQuery = source.ToObjectQuery(); if (sourceQuery == null) throw new ArgumentException("The query must be of type ObjectQuery or DbQuery.", "source"); ObjectContext objectContext = sourceQuery.Context; if (objectContext == null) throw new ArgumentException("The ObjectContext for the source query can not be null.", "source"); EntityMap entityMap = sourceQuery.GetEntityMap<TEntity>(); if (entityMap == null) throw new ArgumentException("Could not load the entity mapping information for the source.", "source"); ObjectQuery<TEntity> objectQuery = query.ToObjectQuery(); if (objectQuery == null) throw new ArgumentException("The query must be of type ObjectQuery or DbQuery.", "query"); return Update(objectContext, entityMap, objectQuery, updateExpression); } /// <summary> /// Executes an update statement using an expression to filter the rows that are updated. /// </summary> /// <typeparam name="TEntity">The type of the entity.</typeparam> /// <param name="source">The source used to determine the table to update.</param> /// <param name="filterExpression">The filter expression used to generate the where clause.</param> /// <param name="updateExpression">The MemberInitExpression used to indicate what is updated.</param> /// <returns>The number of row updated.</returns> /// <example>Update all users in the test.com domain to be inactive. /// <code><![CDATA[ /// var db = new TrackerContext(); /// string emailDomain = "@test.com"; /// int count = db.Users.Update( /// u => u.Email.EndsWith(emailDomain), /// u => new User { IsApproved = false, LastActivityDate = DateTime.Now }); /// ]]></code> /// </example> /// <remarks> /// When executing this method, the statement is immediately executed on the database provider /// and is not part of the change tracking system. Also, changes will not be reflected on /// any entities that have already been materialized in the current context. /// </remarks> public static int Update<TEntity>( this DbSet<TEntity> source, Expression<Func<TEntity, bool>> filterExpression, Expression<Func<TEntity, TEntity>> updateExpression) where TEntity : class { if (source == null) throw new ArgumentNullException("source"); if (filterExpression == null) throw new ArgumentNullException("filterExpression"); return source.Update(source.Where(filterExpression), updateExpression); } private static int Delete<TEntity>(ObjectContext objectContext, EntityMap entityMap, ObjectQuery<TEntity> query) where TEntity : class { DbConnection deleteConnection = null; DbTransaction deleteTransaction = null; DbCommand deleteCommand = null; bool ownConnection = false; bool ownTransaction = false; try { // get store connection and transaction var store = GetStore(objectContext); deleteConnection = store.Item1; deleteTransaction = store.Item2; if (deleteConnection.State != ConnectionState.Open) { deleteConnection.Open(); ownConnection = true; } if (deleteTransaction == null) { deleteTransaction = deleteConnection.BeginTransaction(); ownTransaction = true; } deleteCommand = deleteConnection.CreateCommand(); deleteCommand.Transaction = deleteTransaction; if (objectContext.CommandTimeout.HasValue) deleteCommand.CommandTimeout = objectContext.CommandTimeout.Value; var innerSelect = GetSelectSql(query, entityMap, deleteCommand); var sqlBuilder = new StringBuilder(innerSelect.Length * 2); sqlBuilder.Append("DELETE "); sqlBuilder.Append(entityMap.TableName); sqlBuilder.AppendLine(); sqlBuilder.AppendFormat("FROM {0} AS j0 INNER JOIN (", entityMap.TableName); sqlBuilder.AppendLine(); sqlBuilder.AppendLine(innerSelect); sqlBuilder.Append(") AS j1 ON ("); bool wroteKey = false; foreach (var keyMap in entityMap.KeyMaps) { if (wroteKey) sqlBuilder.Append(" AND "); sqlBuilder.AppendFormat("j0.{0} = j1.{0}", keyMap.ColumnName); wroteKey = true; } sqlBuilder.Append(")"); deleteCommand.CommandText = sqlBuilder.ToString(); int result = deleteCommand.ExecuteNonQuery(); // only commit if created transaction if (ownTransaction) deleteTransaction.Commit(); return result; } finally { if (deleteCommand != null) deleteCommand.Dispose(); if (deleteTransaction != null && ownTransaction) deleteTransaction.Dispose(); if (deleteConnection != null && ownConnection) deleteConnection.Close(); } } private static int Update<TEntity>(ObjectContext objectContext, EntityMap entityMap, ObjectQuery<TEntity> query, Expression<Func<TEntity, TEntity>> updateExpression) where TEntity : class { DbConnection updateConnection = null; DbTransaction updateTransaction = null; DbCommand updateCommand = null; bool ownConnection = false; bool ownTransaction = false; try { // get store connection and transaction var store = GetStore(objectContext); updateConnection = store.Item1; updateTransaction = store.Item2; if (updateConnection.State != ConnectionState.Open) { updateConnection.Open(); ownConnection = true; } // use existing transaction or create new if (updateTransaction == null) { updateTransaction = updateConnection.BeginTransaction(); ownTransaction = true; } updateCommand = updateConnection.CreateCommand(); updateCommand.Transaction = updateTransaction; if (objectContext.CommandTimeout.HasValue) updateCommand.CommandTimeout = objectContext.CommandTimeout.Value; var innerSelect = GetSelectSql(query, entityMap, updateCommand); var sqlBuilder = new StringBuilder(innerSelect.Length * 2); sqlBuilder.Append("UPDATE "); sqlBuilder.Append(entityMap.TableName); sqlBuilder.AppendLine(" SET "); var memberInitExpression = updateExpression.Body as MemberInitExpression; if (memberInitExpression == null) throw new ArgumentException("The update expression must be of type MemberInitExpression.", "updateExpression"); int nameCount = 0; bool wroteSet = false; foreach (MemberBinding binding in memberInitExpression.Bindings) { if (wroteSet) sqlBuilder.AppendLine(", "); string propertyName = binding.Member.Name; string columnName = entityMap.PropertyMaps .Where(p => p.PropertyName == propertyName) .Select(p => p.ColumnName) .FirstOrDefault(); string parameterName = "p__update__" + nameCount++; var memberAssignment = binding as MemberAssignment; if (memberAssignment == null) throw new ArgumentException("The update expression MemberBinding must only by type MemberAssignment.", "updateExpression"); object value; if (memberAssignment.Expression.NodeType == ExpressionType.Constant) { var constantExpression = memberAssignment.Expression as ConstantExpression; if (constantExpression == null) throw new ArgumentException("The MemberAssignment expression is not a ConstantExpression.", "updateExpression"); value = constantExpression.Value; } else { LambdaExpression lambda = Expression.Lambda(memberAssignment.Expression, null); value = lambda.Compile().DynamicInvoke(); } var parameter = updateCommand.CreateParameter(); parameter.ParameterName = parameterName; parameter.Value = value; updateCommand.Parameters.Add(parameter); sqlBuilder.AppendFormat("{0} = @{1}", columnName, parameterName); wroteSet = true; } sqlBuilder.AppendLine(" "); sqlBuilder.AppendFormat("FROM {0} AS j0 INNER JOIN (", entityMap.TableName); sqlBuilder.AppendLine(); sqlBuilder.AppendLine(innerSelect); sqlBuilder.Append(") AS j1 ON ("); bool wroteKey = false; foreach (var keyMap in entityMap.KeyMaps) { if (wroteKey) sqlBuilder.Append(" AND "); sqlBuilder.AppendFormat("j0.{0} = j1.{0}", keyMap.ColumnName); wroteKey = true; } sqlBuilder.Append(")"); updateCommand.CommandText = sqlBuilder.ToString(); int result = updateCommand.ExecuteNonQuery(); // only commit if created transaction if (ownTransaction) updateTransaction.Commit(); return result; } finally { if (updateCommand != null) updateCommand.Dispose(); if (updateTransaction != null && ownTransaction) updateTransaction.Dispose(); if (updateConnection != null && ownConnection) updateConnection.Close(); } } private static Tuple<DbConnection, DbTransaction> GetStore(ObjectContext objectContext) { DbConnection dbConnection = objectContext.Connection; var entityConnection = dbConnection as EntityConnection; // by-pass entity connection if (entityConnection == null) return new Tuple<DbConnection, DbTransaction>(dbConnection, null); DbConnection connection = entityConnection.StoreConnection; // get internal transaction dynamic connectionProxy = new DynamicProxy(entityConnection); dynamic entityTransaction = connectionProxy.CurrentTransaction; if (entityTransaction == null) return new Tuple<DbConnection, DbTransaction>(connection, null); DbTransaction transaction = entityTransaction.StoreTransaction; return new Tuple<DbConnection, DbTransaction>(connection, transaction); } private static string GetSelectSql<TEntity>(ObjectQuery<TEntity> query, EntityMap entityMap, DbCommand command) where TEntity : class { // changing query to only select keys var selector = new StringBuilder(50); selector.Append("new("); foreach (var propertyMap in entityMap.KeyMaps) { if (selector.Length > 4) selector.Append((", ")); selector.Append(propertyMap.PropertyName); } selector.Append(")"); var selectQuery = DynamicQueryable.Select(query, selector.ToString()); var objectQuery = selectQuery as ObjectQuery; if (objectQuery == null) throw new ArgumentException("The query must be of type ObjectQuery.", "query"); string innerJoinSql = objectQuery.ToTraceString(); // create parameters foreach (var objectParameter in objectQuery.Parameters) { var parameter = command.CreateParameter(); parameter.ParameterName = objectParameter.Name; parameter.Value = objectParameter.Value; command.Parameters.Add(parameter); } return innerJoinSql; } }}(转)EntityFramework.Extensions的更多相关文章
- 测试EntityFramework,Z.EntityFramework.Extensions,原生语句在不同的查询中的表现。原来池化与非池化设定是有巨大的影响的。
Insert测试,只测试1000条的情况,多了在实际的项目中应该就要另行处理了. using System; using System.Collections.Generic; using Syste ...
- 第九节: EF的性能篇(二) 之 Z.EntityFramework.Extensions程序集解决EF的性能问题
一. 综述 该模块主要介绍:EF的性能优化插件Z.EntityFramework.Extensions,该插件收费. (一). 简介 1. 相关网站:http://www.zzzprojects.co ...
- 【EF】解决EF批量操作,Z.EntityFramework.Extensions 过期方案
方案一: 使用EntityFramework.Extended优点: 启下载量是Z.EntityFramework.Extensions的10倍+ 不会过期缺点:不能批量Insert 方案二:解决批量 ...
- 破解EFCore扩展Dll --- Z.EntityFramework.Extensions.EFCore
安装 Z.EntityFramework.Extensions.EFCore Install-Package Z.EntityFramework.Extensions.EFCore -Version ...
- 自己动手破解Z.EntityFramework.Extensions 4.0.11.0的方法
因为项目中使用到Z.EntityFramework.Extensions 和 Z.EntityFramework.Plus(免费开源)两个类库,但是Z.EntityFramework.Extensio ...
- EF 批量增删改 EntityFramework.Extensions
EntityFramework.Extensions 1.官方网站 http://entityframework-extensions.net/ 2 破解版 Z.EntityFramework.E ...
- EF批量插入数据(Z.EntityFramework.Extensions)
EF用原生的插入数据方法DbSet.ADD()和 DbSet.AddRange()都很慢.所以要做大型的批量插入只能另选它法. 1.Nugget 2.代码 using EF6._0Test.EF; u ...
- 采用EntityFramework.Extended 对EF进行扩展(Entity Framework 延伸系列2)
前言 Entity Framework 延伸系列目录 今天我们来讲讲EntityFramework.Extended 首先科普一下这个EntityFramework.Extended是什么,如下: 这 ...
- EntityFramework 优化建议
Entity Framework目前最新版本是6.1.3,当然Entity Framework 7 目前还是预览版,并不能投入正式生产环境,估计正式版16年第一季度会出来,了解过EF7的部分新特性后, ...
随机推荐
- H5笔记周记
9.4 一.介绍浏览器 1.title 主题,题目 2.url 网址 3.body 网站的内容 4.html 语言,超文本标记语言 二.文件介绍 三.标签的结构 (一些快捷键:Ctrl+s 保存 ...
- hdu 5461(2015沈阳网赛 简单暴力) Largest Point
题目;http://acm.hdu.edu.cn/showproblem.php?pid=5461 题意就是在数组中找出a*t[i]*t[i]+b*t[j]的最大值,特别注意的是这里i和i不能相等,想 ...
- dbus 消息和消息总线实例讲解-二
转自:http://www.fmddlmyy.cn/text53.html 2.3.2.ListActivatableNames和服务器的自动启动 运行: $ dbus-send --system - ...
- 如何为linux系统设置全局的默认网络代理
方法1:更改全局配置文件/etc/profile all_proxy="all_proxy=socks://proxy.xxx.com.cn:80/" ftp_proxy=&quo ...
- eclipse自动添加javadoc注释
参考文档: https://jingyan.baidu.com/article/36d6ed1f70ea9c1bce488350.html https://www.cnblogs.com/yangji ...
- 简单的node 服务端 响应get,返回json数据;
原文:http://blog.csdn.net/xn_28/article/details/50837019 const http = require('http'); const hostname ...
- pycharm 创建文件时,自动添加文件头注释
File->settings->Editor->File and Code Templates->Python Script # -*- coding: utf-8 -*- & ...
- redis在游戏服务器中的使用初探(三) 信息存储
摘要: 搭建了服务器环境 有了客户端 我们来假想下以下应用场景:我们简单举个实例来描述下Hash的应用场景,比如我们要存储一个用户信息对象数据,包含以下信息:用户ID,为查找的key,存储的value ...
- g2o相关问题cs.h,以及no matching function for call to ‘g2o::OptimizationAlgorithmLevenberg::OptimizationAlgorithmLevenberg(Block*&)
1.对于cs.h找不到的情况 1)编译的时候一定要把csparse在EXTERNAL文件中,编译进去. 2)修改CMakeLists.txt文件中的include_directories中的${CPA ...
- socket.io的connect连接时不断的进行自动连接,并产生错误net::ERR_EMPTY_RESPONSE
socket = io.connect('http://192.168.1.200:9043?uuid=333'); 执行上面的语句时,产生下面的错误: 后来经过排查,是由于项目的jdk版本过低引起的 ...