(转)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的部分新特性后, ...
随机推荐
- StackExchange.Redis使用以及封装
来源:http://www.cnblogs.com/qtqq/p/5951201.html Redis安装:http://www.runoob.com/redis/redis-install.html ...
- Win10以管理员身份启动cmd.exe
PowerShell -windowstyle hidden -Command "Start-Process cmd.exe -ArgumentList '/s,/k, pushd' -Ve ...
- vue.js路由vue-router
学习网址:https://segmentfault.com/blog/vueroad 转载至:https://segmentfault.com/a/1190000009350679#articleHe ...
- echart.js组件编写
1.传参 <area-chart :chartdata='monitorTimes' :datatype='typeSelected' :dataX = '"tid"' :t ...
- DevExpress如何实现皮肤的添加及本地化
DevExpress.XtraBars.Helpers.SkinHelper类允许您填充现有RibbonGalleryBarItem或任意菜单(PopupMenu或BarSubItem)项目对应的De ...
- vs的【warning C4996:'fopen': This function or variable may be unsafe】解决方案
编译警告:warning C4996 与 Security Enhancements in the CRT 将过去的工程用VS2005打开的时候.你有可能会遇到一大堆的警告:warning C4996 ...
- PAT 1009 说反话 (20)(代码)
1009 说反话 (20)(20 分) 给定一句英语,要求你编写程序,将句中所有单词的顺序颠倒输出. 输入格式:测试输入包含一个测试用例,在一行内给出总长度不超过80的字符串.字符串由若干单词和若干空 ...
- mysql 5.17 的update失败问题
在使用workbench的时候,写入update语句,会很提现失败,原因是安全模式; 可能是workbench在数据库更新的时候是有限制的,防止错误哦l 更改方法也很简单; Edit - Profer ...
- 通过 ulimit 改善系统性能
系统性能一直是一个受关注的话题,如何通过最简单的设置来实现最有效的性能调优,如何在有限资源的条件下保证程序的运作,ulimit 是我们在处理这些问题时,经常使用的一种简单手段.ulimit 是一种 l ...
- Scrapy shell调试返回403错误
一.问题描述 有时候用scrapy shell来调试很方便,但是有些网站有防爬虫机制,所以使用scrapy shell会返回403,比如下面 C:\Users\fendo>scrapy shel ...