I have the following function which is actually a wrapper around Z.EntityFramework.Plus bulk update:
public static int UpdateBulk<T>(this IQueryable<T> query, Expression<Func<T, T>> updateFactory) where T : IBaseEntity, new()
{
Expression<Func<T, T>> modifiedExpression = x => new T() { ModifiedBy = "Test", ModifiedDate = DateTime.Now };
var combine = Expression.Lambda<Func<T, T>>(
Expression.AndAlso(
Expression.Invoke(updateFactory, updateFactory.Parameters),
Expression.Invoke(modifiedExpression, modifiedExpression.Parameters)
),
updateFactory.Parameters.Concat(modifiedExpression.Parameters)
); //This returns an error
return query.Update(combine);
}
Called like this:
decimal probId = ProbId.ParseDecimal();
db.Problems
.Where(e => e.ProbId == probId)
.UpdateBulk(e => new Problem() {
CatId = Category.ParseNullableInt(),
SubCatId = SubCategory.ParseNullableInt(),
ListId = Problem.ParseNullableInt()
});
Where IBaseEntity is defined as follows:
public abstract class IBaseEntity
{
public System.DateTime CreatedDate { get; set; }
public string CreatedBy { get; set; }
public System.DateTime ModifiedDate { get; set; }
public string ModifiedBy { get; set; }
public string DeletedBy { get; set; }
}
The 'Problem' class by the way implements IBaseEntity.
What I want to do is automatically append ModifiedBy and ModifiedDate to updateFactory in the UpdateBulk function so that this doesn't have to be done in every call to UpdateBulk.
I tried in the above UpdateBulk function to combine the parsed 'updateFactory' expression with the 'modifiedExpression' but it returns the error:
the binary operator AndAlso is not defined for the types 'Problem'
Is it possible to merge Expression like this and if so, what am I doing wrong? If not, how can I merge ModifiedBy = "Test", ModifiedDate = DateTime.Now into the updateFactory expression?
Thanks, Rod
c for source and . h fpr header files is just a convention, and the compiler uses that as defaults. Normally you only include header files containing some standard definitions (macro definitions, struct/union or typedef declarations, etc.). But the compiler has no problem when you include one source file into another.
Basically linking or including is done by #include<filename> or #include”filename” in C++. Now, as per your question, two c++ files can be linked by using #include”filename. cpp” , if all the files are in same directory. Otherwise specify the directory name before the filename.
You cannot use AndAlso
, since that's meant for the BinaryExpression - Expression<Func<T,bool>>
, In this case you need Expression Visitor, as defined here by Marc Gravell (so he deserves all the credit)
I am using the same to provide a solution in your case, with an assumption of Problem class schema
, pasting the Linqpad code:
void Main()
{
var final = UpdateBulk((Problem p) => new Problem{CatId = 1,SubCatId = 2, ListId=3});
// final is of type Expression<Func<T,T>>, which can be used for further processing
final.Dump();
}
public static Expression<Func<T, T>> UpdateBulk<T>(Expression<Func<T, T>> updateFactory) where T : IBaseEntity, new()
{
Expression<Func<T, T>> modifiedExpression = x => new T() { ModifiedBy = "Test", ModifiedDate = DateTime.Now };
var result = Combine(updateFactory, modifiedExpression);
return result;
}
static Expression<Func<TSource, TDestination>> Combine<TSource, TDestination>(
params Expression<Func<TSource, TDestination>>[] selectors)
{
var param = Expression.Parameter(typeof(TSource), "x");
return Expression.Lambda<Func<TSource, TDestination>>(
Expression.MemberInit(
Expression.New(typeof(TDestination).GetConstructor(Type.EmptyTypes)),
from selector in selectors
let replace = new ParameterReplaceVisitor(
selector.Parameters[0], param)
from binding in ((MemberInitExpression)selector.Body).Bindings
.OfType<MemberAssignment>()
select Expression.Bind(binding.Member,
replace.VisitAndConvert(binding.Expression, "Combine")))
, param);
}
class ParameterReplaceVisitor : ExpressionVisitor
{
private readonly ParameterExpression from, to;
public ParameterReplaceVisitor(ParameterExpression from, ParameterExpression to)
{
this.from = from;
this.to = to;
}
protected override Expression VisitParameter(ParameterExpression node)
{
return node == from ? to : base.VisitParameter(node);
}
}
public abstract class IBaseEntity
{
public System.DateTime CreatedDate { get; set; }
public string CreatedBy { get; set; }
public System.DateTime ModifiedDate { get; set; }
public string ModifiedBy { get; set; }
public string DeletedBy { get; set; }
}
public class Problem : IBaseEntity
{
public int CatId { get; set; }
public int SubCatId { get; set; }
public int ListId { get; set; }
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With