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"
);
&nb