(转)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的部分新特性后, ...
随机推荐
- mysql联表更新使用join
update TableA as a inner join TableB as b on a.order_id=b.order_id set a.last_time='2018-01-01' whe ...
- angular2.0学习笔记1.开发环境搭建 (node.js和npm的安装)
开发环境, 1.安装Node.js®和npm, node 6.9.x 和 npm 3.x.x 以上的版本. 更老的版本可能会出现错误,更新的版本则没问题. 控制台窗口中运行命令 node -v 和 n ...
- [Jmeter] 用xsltproc生成html格式的报告
1.下载xsltproc 下载地址:ftp://ftp.zlatkovic.com/libxml/libxslt-1.1.26.win32.zip 其中包含我们所需要的xsltproc可执行文件:xs ...
- Mockplus3.5.0.1新增标注功能
Mockplus3.5.0.1版本中,新增了标注功能.多种标注模式,智能生成,随时查看.原型设计效率更高. Mockplus的标注功能有以下四种模式: 1.无选中标注 在未选中任何组件时,按住Ctrl ...
- Sort Array By Parity LT905
Given an array A of non-negative integers, return an array consisting of all the even elements of A, ...
- Windows server 2008 被ntlmssp安装攻击 解决
进行NTLM策略控制,彻底阻止LM响应
- crud树型结构数据
小型数据,比如标签,部门之类的,可以组织数据,成层状结构,一并返回前端,节省请求次数:但是大型数据,比如省市区等等联动,如果一并返回组织好的数据,查询量大,页面多次刷新,恶意请求,放入缓存还可以,其实 ...
- java20(判断是否为会员)
1.不确定数组是哪个类型是,将数据类型换成类名 2.记得将判断的参数传到方法中 3.用到类名的: 创建对象时 创建未知类型的数组时 4.创建的对象所用到的名字,体重,判断(boolean isvip ...
- spring学习 十四 注解AOP 通知传递参数
我们在对切点进行增强时,不建议对切点进行任何修改,因此不加以使用@PointCut注解打在切点上,尽量只在Advice上打注解(Before,After等),如果要在通知中接受切点的参数,可以使用Jo ...
- js网页上画图
保存 1.d3.js (http://www.d3.org/)使用svg技术,展示大数据量,动态效果很好,但是API暴露的不好,得靠自己摸索. 2.http://raphaeljs.com/refe ...