(转)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的部分新特性后, ...
随机推荐
- Winrar发现损坏的压缩文件头
解决方法: 点击"解压到"-->保留损坏文件
- mysql导入慢解决方法
[mysqldump]max_allowed_packet = 512M [mysqld] interactive_timeout = 120 innodb_change_buffering=alli ...
- CSS 图片居中
} .left-logo a { height: 100px; width: 55px; display: block; } .left-logo a img{ height: ; width: 55 ...
- js DomContentLoaded 和 load 的区别
如题:DOMContentLoaded和load都是页面加载的时候触发的事件.区别在于触发的时机不一样. 浏览器渲染页面DOM文档加载的步骤: 1.解析HTML结构. 2.加载外部脚本和css文件. ...
- 自定义标签tld的使用
在JSP中使用标签是很平常的事情,在制作自定义标签时,通常都需要写tld文件来定义标签的各种属性,对应的Java类,前缀等等.标签与tld文件紧紧相连,那么,到底应该怎么放置tld文件?在web.xm ...
- VFIO简介 (转载)
VFIO简介 LTCChina | Nov 20 2013 | Comment (1) | Visits (15204) 概述 VFIO是一套用户态驱动框架,它提供两种基本服务: 向用户态提供访问硬件 ...
- 图片延时加载原理 和 使用jquery实现的一个图片延迟加载插件(含图片延迟加载原理)
图片加载技术分为:图片预加载和图片延时加载. javascript图片预加载和延时加载的区别主要体现在图片传输到客户端的时机上,都是为了提升用户体验的,延时加载又叫懒加载.两种技术的本质:两者的行为是 ...
- 201621123008 《Java程序设计》第13周学习总结
1. 本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 2. 为你的系统增加网络功能(购物车.图书馆管理.斗地主等)-分组完成 为了让你的系统可以被多个用户通过网 ...
- 无法创建.gitignore文件,提示必须输入文件名称
If you're using Windows it will not let you create a file without a filename in Windows Explorer. It ...
- serial -1
#include <reg52.h>#include <stdio.h>#define uchar unsigned charsbit LED = P2^2;uchar rec ...