How to compare only date part with linq expression? - linq

I just want to make Column Filter for grid view. Simple I just want to filter grid view column with some extra stuff. Here I have created one IQueryable that returns queryable result.
Here is my code :
------------------------------------------Updated------------------------------------------------
public static IQueryable<T> FilterForColumn<T>(this IQueryable<T> queryable, string colName, string searchText)
{
if (colName != null && searchText != null)
{
var parameter = Expression.Parameter(typeof(T), "m");
var propertyExpression = Expression.Property(parameter, colName);
System.Linq.Expressions.ConstantExpression searchExpression = null;
System.Reflection.MethodInfo containsMethod = null;
System.Linq.Expressions.MethodCallExpression body = null;
System.Nullable<DateTime> nextDate = null;
Expression ex1 = null;
Expression ex2 = null;
switch (colName)
{
case "JobID":
case "FileSize":
case "TotalFileSize":
Int64? size = Convert.ToInt64(searchText);
searchExpression = Expression.Constant(searchText);
containsMethod = typeof(Int64?).GetMethod("Equals", new[] { typeof(Int64?) });
body = Expression.Call(propertyExpression, containsMethod, searchExpression);
break;
case "PublishDate":
case "Birth_date":
case "Anniversary_date":
case "Profile_Updated_datetime":
case "CompletedOn":
DateTime? currentDate = DateTime.ParseExact(searchText, "dd/MM/yyyy", null);
nextDate = currentDate.Value.AddDays(1);
ex1 = Expression.GreaterThanOrEqual(propertyExpression, Expression.Constant(currentDate));
ex2 = Expression.LessThan(propertyExpression, Expression.Constant(nextDate));
body = Expression.AndAlso(ex1, ex2);
break;
case "Created_datetime":
case "Reminder_Date":
case "News_date":
case "thought_date":
case "SubscriptionDateTime":
case "Register_datetime":
case "CreatedOn":
DateTime dt1 = DateTime.ParseExact(searchText, "dd/MM/yyyy", null);
nextDate = currentDate.Value.AddDays(1);
ex1 = Expression.GreaterThanOrEqual(propertyExpression, Expression.Constant(currentDate));
ex2 = Expression.LessThan(propertyExpression, Expression.Constant(nextDate));
body = Expression.AndAlso(ex1, ex2);
break;
default :
searchExpression = Expression.Constant(searchText);
containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) });
body = Expression.Call(propertyExpression, containsMethod, searchExpression);
break;
}
var predicate = Expression.Lambda<Func<T, bool>>(body, new[] { parameter });
return queryable.Where(predicate);
}
else
{
return queryable;
}
}
here this solution gives some compile time error :
Error 9 Cannot implicitly convert type 'System.Linq.Expressions.BinaryExpression' to 'System.Linq.Expressions.MethodCallExpression' F:\EasyWeb\App_Code\Helper.cs 47 28 F:\EasyWeb\
Here at case of DateTime I just want to filter DateTime column with only Date not whole DATETIME value.
Here I just put required things :
SELECT [t8].[Id], [t8].[Title], [t8].[value] AS [Publisher], [t8].[value2] AS [ToUser], [t8].[Sent_Datetime] AS [PublishDate], [t8].[IsFileAttached] AS [IsFile], [t8].[Category_name] AS [CategoryName], [t8].[value3] AS [status_name], [t8].[value4] AS [Group_name], [t8].[TotalFileSize] AS [FileSize]
FROM (
SELECT [t0].[Id], [t0].[Title], (
SELECT TOP (1) [t3].[value]
FROM (
SELECT ([t2].[First_name] + ' ') + [t2].[Last_name] AS [value], [t2].[Id]
FROM [dbo].[tbl_User_master] AS [t2]
) AS [t3]
WHERE [t3].[Id] = [t0].[User_id]
) AS [value], (
SELECT TOP (1) [t5].[value]
FROM (
SELECT ([t4].[First_name] + ' ') + [t4].[Last_name] AS [value], [t4].[Id]
FROM [dbo].[tbl_User_master] AS [t4]
) AS [t5]
WHERE ([t5].[Id]) = [t0].[ToUser_id]
) AS [value2], [t0].[Sent_Datetime], [t0].[IsFileAttached], [t1].[Category_name], (
SELECT TOP (1) [t6].[status_name]
FROM [dbo].[tbl_status_master] AS [t6]
WHERE ([t6].[Id]) = [t0].[status_id]
) AS [value3], (
SELECT TOP (1) [t7].[Group_name]
FROM [dbo].[tbl_Group_master] AS [t7]
WHERE ([t7].[Id]) = [t0].[group_id]
) AS [value4], [t0].[TotalFileSize], [t0].[ToUser_id], [t0].[User_id]
FROM [dbo].[tbl_Post_History] AS [t0]
INNER JOIN [dbo].[tbl_Category_master] AS [t1] ON [t0].[Category_id] = [t1].[Id]
) AS [t8]
WHERE (CAST(CONVERT(CHAR(10), [t8].[Sent_Datetime], 102) AS DATETIME) = '12/24/2013' ) AND (([t8].[ToUser_id] = 3) OR ([t8].[ToUser_id] IS NULL)) AND ([t8].[User_id] <> 3)
ORDER BY [t8].[Sent_Datetime] DESC
Here this shows required output or logic that we will do with queryable.
But, here one drawback occurs while this method Equals check whole Date Time.
Is that possible with this method to force only check Date Part from column?
------------------------------------2-Updated-----------------------------------------
for overwhelming this problem i use this technique :
public static IQueryable<T> FilterForColumn<T>(this IQueryable<T> queryable, string colName, string searchText)
{
if (colName != null && searchText != null)
{
var parameter = Expression.Parameter(typeof(T), "m");
var propertyExpression = Expression.Property(parameter, colName);
System.Linq.Expressions.ConstantExpression searchExpression = null;
System.Reflection.MethodInfo containsMethod = null;
System.Linq.Expressions.BinaryExpression body = null;
DateTime? currentDate = null;
DateTime? nextDate = null;
Expression ex1 = null;
Expression ex2 = null;
switch (colName)
{
case "JobID":
case "FileSize":
case "TotalFileSize":
Int64? size = Convert.ToInt64(searchText);
searchExpression = Expression.Constant(searchText);
containsMethod = typeof(Int64?).GetMethod("Equals", new[] { typeof(Int64?) });
//body = Expression.Call(propertyExpression, containsMethod, searchExpression);
break;
case "PublishDate":
case "Birth_date":
case "Anniversary_date":
case "Profile_Updated_datetime":
case "CompletedOn":
currentDate = DateTime.ParseExact(searchText, "dd/MM/yyyy", null);
nextDate = currentDate.Value.AddDays(1);
ex1 = Expression.GreaterThanOrEqual(propertyExpression, Expression.Constant(currentDate));
ex2 = Expression.LessThan(propertyExpression, Expression.Constant(nextDate));
body = Expression.AndAlso(ex1, ex2);
break;
case "Created_datetime":
case "Reminder_Date":
case "News_date":
case "thought_date":
case "SubscriptionDateTime":
case "Register_datetime":
case "CreatedOn":
currentDate = DateTime.ParseExact(searchText, "dd/MM/yyyy", null);
nextDate = currentDate.Value.AddDays(1);
ex1 = Expression.GreaterThanOrEqual(propertyExpression, Expression.Constant(currentDate));
ex2 = Expression.LessThan(propertyExpression, Expression.Constant(nextDate));
body = Expression.AndAlso(ex1, ex2);
break;
default :
searchExpression = Expression.Constant(searchText);
containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) });
//body = Expression.Call(propertyExpression, containsMethod, searchExpression);
break;
}
var predicate = Expression.Lambda<Func<T, bool>>(body, new[] { parameter });
return queryable.Where(predicate);
}
else
{
return queryable;
}
}
it's give me run time error like :
Server Error in '/EasyWeb' Application.
The binary operator GreaterThanOrEqual is not defined for the types 'System.Nullable`1[System.DateTime]' and 'System.DateTime'.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.InvalidOperationException: The binary operator GreaterThanOrEqual is not defined for the types 'System.Nullable`1[System.DateTime]' and 'System.DateTime'.
Source Error:
Line 44: currentDate = DateTime.ParseExact(searchText, "dd/MM/yyyy", null);
Line 45: nextDate = currentDate.Value.AddDays(1);
Line 46: ex1 = Expression.GreaterThanOrEqual(propertyExpression, Expression.Constant(currentDate));
Line 47: ex2 = Expression.LessThan(propertyExpression, Expression.Constant(nextDate));
Line 48: body = Expression.AndAlso(ex1, ex2);
Source File: f:\EasyWeb\App_Code\Helper.cs Line: 46
Stack Trace:
[InvalidOperationException: The binary operator GreaterThanOrEqual is not defined for the types 'System.Nullable`1[System.DateTime]' and 'System.DateTime'.]
System.Linq.Expressions.Expression.GetUserDefinedBinaryOperatorOrThrow(ExpressionType binaryType, String name, Expression left, Expression right, Boolean liftToNull) +752213
System.Linq.Expressions.Expression.GetComparisonOperator(ExpressionType binaryType, String opName, Expression left, Expression right, Boolean liftToNull) +221
System.Linq.Expressions.Expression.GreaterThanOrEqual(Expression left, Expression right, Boolean liftToNull, MethodInfo method) +53
System.Linq.Expressions.Expression.GreaterThanOrEqual(Expression left, Expression right) +8
Helper.FilterForColumn(IQueryable`1 queryable, String colName, String searchText) in f:\EasyWeb\App_Code\Helper.cs:46
Admin_Post_History.FillGrid(String CommandName, String ColumnName, String SearchText) in f:\EasyWeb\Admin\Post_History.aspx.cs:79
Admin_Post_History.btnsearch_Click(Object sender, EventArgs e) in f:\EasyWeb\Admin\Post_History.aspx.cs:2375
System.Web.UI.WebControls.Button.OnClick(EventArgs e) +111
System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +110
System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +10
System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +13
System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +36
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1565
Version Information: Microsoft .NET Framework Version:2.0.50727.3053; ASP.NET Version:2.0.50727.3053
-------------------------------- 3 Update-------------------------------------------
here is what i'm querying :
case "Inbox":
lbl_disply.Text = "Inbox";
lbut_showinbox.Font.Bold = true;
lbut_showoutbox.Font.Bold = false;
lbut_showdraffs.Font.Bold = false;
lbut_showtrash.Font.Bold = false;
var query1 = db.Posts.Where(p => (p.ToUser_id.Equals(user_id) || p.ToUser_id.Equals(null)) && p.User_id != user_id).OrderByDescending(p=>p.Sent_Datetime).Select(p => new
{
Id = p.Id,
Title = p.Title,
Publisher = db.Users.Where(u => u.Id.Equals(p.User_id)).Select(u => u.First_name + ' ' + u.Last_name).FirstOrDefault(),
ToUser = db.Users.Where(u => u.Id.Equals(p.ToUser_id)).Select(u => u.First_name + ' ' + u.Last_name).FirstOrDefault(),
PublishDate = p.Sent_Datetime,
IsFile = p.IsFileAttached,
CategoryName = db.Categories.Where(c => c.Id.Equals(p.Category_id)).Select(c => c.Category_name).FirstOrDefault(),
status_name = db.Status.Where(s => s.Id.Equals(p.status_id)).Select(s => s.status_name).FirstOrDefault(),
Group_name = db.Groups.Where(g => g.Id.Equals(p.group_id)).Select(g => g.Group_name).FirstOrDefault(),
FileSize = p.TotalFileSize
}).FilterForColumn(ColumnName, SearchText).ToList();
at grid view filling
DataSet myDataSet = new DataSet();
DataTable dt = new DataTable();
dt.Columns.Add(new DataColumn("Id", typeof(int)));
dt.Columns.Add(new DataColumn("IsRead", typeof(bool)));
dt.Columns.Add(new DataColumn("IsImp", typeof(bool)));
dt.Columns.Add(new DataColumn("Title", typeof(string)));
dt.Columns.Add(new DataColumn("Publisher", typeof(string)));
dt.Columns.Add(new DataColumn("ToUser", typeof(string)));
dt.Columns.Add(new DataColumn("PublishDate", typeof(DateTime?)));
dt.Columns.Add(new DataColumn("IsFile", typeof(bool)));
dt.Columns.Add(new DataColumn("CategoryName", typeof(string)));
dt.Columns.Add(new DataColumn("status_name", typeof(string)));
dt.Columns.Add(new DataColumn("Group_name", typeof(string)));
dt.Columns.Add(new DataColumn("FileSize", typeof(string)));
foreach (var item in query1)
i declared this PublishDate as typeof(DateTime?) but this gives me run time error like :
Server Error in '/EasyWeb' Application.
DataSet does not support System.Nullable<>.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.NotSupportedException: DataSet does not support System.Nullable<>.
Source Error:
Line 101: dt.Columns.Add(new DataColumn("Publisher", typeof(string)));
Line 102: dt.Columns.Add(new DataColumn("ToUser", typeof(string)));
Line 103: dt.Columns.Add(new DataColumn("PublishDate", typeof(DateTime?)));
Line 104: dt.Columns.Add(new DataColumn("IsFile", typeof(bool)));
Line 105: dt.Columns.Add(new DataColumn("CategoryName", typeof(string)));
Source File: f:\EasyWeb\Admin\Post_History.aspx.cs Line: 103
Stack Trace:
[NotSupportedException: DataSet does not support System.Nullable<>.]
System.Data.DataColumn..ctor(String columnName, Type dataType, String expr, MappingType type) +4826536
System.Data.DataColumn..ctor(String columnName, Type dataType) +12
Admin_Post_History.FillGrid(String CommandName, String ColumnName, String SearchText) in f:\EasyWeb\Admin\Post_History.aspx.cs:103
Admin_Post_History.Page_Load(Object sender, EventArgs e) in f:\EasyWeb\Admin\Post_History.aspx.cs:59
System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +14
System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +35
System.Web.UI.Control.OnLoad(EventArgs e) +99
System.Web.UI.Control.LoadRecursive() +50
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +627
Version Information: Microsoft .NET Framework Version:2.0.50727.3053; ASP.NET Version:2.0.50727.3053
---------------------------------4 Update----------------------------------------
i check my dbml file and this is screen shot for verify that it's nullable

To achieve what you want you can use predicate
WHERE Sent_Datetime >= '20131224' AND Sent_Datetime < '20131225'
so you can use this expression
DateTime currentDate = DateTime.ParseExact("06/01/2008", "dd/MM/yyyy", null);
DateTime nextDate = currentDate.AddDays(1);
Expression ex1 = Expression.GreaterThanOrEqual(
propertyExpression, Expression.Constant(currentDate));
Expression ex2 = Expression.LessThan(
propertyExpression, Expression.Constant(nextDate));
Expression body = Expression.AndAlso(ex1, ex2);
var predicate = Expression.Lambda<Func<T, bool>>(body, new[] { parameter });
Of course, here you have sargable predicate.
Update
I've created the complete example for you:
public static IQueryable<T> FilterForColumn<T>(this IQueryable<T> queryable, string colName, string searchText)
{
if (colName != null && searchText != null)
{
var parameter = Expression.Parameter(typeof(T), "m");
var propertyExpression = Expression.Property(parameter, colName);
System.Linq.Expressions.ConstantExpression searchExpression = null;
System.Reflection.MethodInfo containsMethod = null;
// this must be of type Expression to accept different type of expressions
// i.e. BinaryExpression, MethodCallExpression, ...
System.Linq.Expressions.Expression body = null;
Expression ex1 = null;
Expression ex2 = null;
switch (colName)
{
case "JobID":
case "FileSize":
case "TotalFileSize":
Int64? size = Convert.ToInt64(searchText);
searchExpression = Expression.Constant(searchText);
containsMethod = typeof(Int64?).GetMethod("Equals", new[] { typeof(Int64?) });
body = Expression.Call(propertyExpression, containsMethod, searchExpression);
break;
// section for DateTime? properties
case "PublishDate":
case "Birth_date":
case "Anniversary_date":
case "Profile_Updated_datetime":
case "CompletedOn":
DateTime currentDate = DateTime.ParseExact(searchText, "dd/MM/yyyy", null);
DateTime nextDate = currentDate.AddDays(1);
ex1 = Expression.GreaterThanOrEqual(propertyExpression, Expression.Constant(currentDate, typeof(DateTime?)));
ex2 = Expression.LessThan(propertyExpression, Expression.Constant(nextDate, typeof(DateTime?)));
body = Expression.AndAlso(ex1, ex2);
break;
// section for DateTime properties
case "Created_datetime":
case "Reminder_Date":
case "News_date":
case "thought_date":
case "SubscriptionDateTime":
case "Register_datetime":
case "CreatedOn":
DateTime currentDate = DateTime.ParseExact(searchText, "dd/MM/yyyy", null);
DateTime nextDate = currentDate.AddDays(1);
ex1 = Expression.GreaterThanOrEqual(propertyExpression, Expression.Constant(currentDate));
ex2 = Expression.LessThan(propertyExpression, Expression.Constant(nextDate));
body = Expression.AndAlso(ex1, ex2);
break;
default :
searchExpression = Expression.Constant(searchText);
containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) });
body = Expression.Call(propertyExpression, containsMethod, searchExpression);
break;
}
var predicate = Expression.Lambda<Func<T, bool>>(body, new[] { parameter });
return queryable.Where(predicate);
}
else
{
return queryable;
}
}

You can use the SqlFunctions.DateDiff function specifying "day" value as datepart parameter.
var result = entities
.Where(item =>
SqlFunctions.DateDiff("day", item.DateProperty, dateToCompare) == 0);

Related

Why does my audit trail code cause a concurrency error?

The environment is React, .NET Core 2.2.5, Oracle EF Core 2.19.30, Oracle 12c.
I am using the following code to add change log entries whenever an entity is changed in some way. Everything I've seen on Google indicates this should work. However, when it gets to the "base.SaveChanges()" call, I get the error "database operation expected to affect 1 row(s) but actually affected 5 row(s)". If I remove the change log code and just call "base.SaveChanges()", it works fine and does update the expected row, so the issue is clearly related to the change log entries itself.
I've seen this error on Google, but the actual number is always 0, never more. The other strange thing is that every time I run the code, the "actual" number increases by 5 (I'm up to 95 at the moment, and that's after I rebooted), which does happen to be the number of change log entries that should be added.
I don't see anything unusual in my situation, other than I'm using Oracle (I plan on testing this with SQL Server at home soon).
public override int SaveChanges()
{
List<EntityEntry> entries = ChangeTracker.Entries().Where(x => x.State == EntityState.Added || x.State == EntityState.Modified || x.State == EntityState.Deleted).ToList();
foreach (EntityEntry entry in entries.ToArray())
{
string tableName = new SafetyDataContext().Model.FindEntityType(entry.Entity.GetType()).Relational().TableName;
string keyData = GetPrimaryKeyValue(entry);
if (entry.State == EntityState.Added)
{
PropertyValues currentValues = entry.CurrentValues;
for (int i = 0; i < currentValues.Properties.Count; i++)
{
string columnName = currentValues.Properties[i].Relational().ColumnName;
string newValue = currentValues[currentValues.Properties[i].Name] != null ? currentValues[currentValues.Properties[i].Name].ToString() : string.Empty;
EntityChangeModel log = new EntityChangeModel()
{
Change_Type = "ADD",
Change_Date = DateTime.Now,
Change_User_ID = 0,
Table_Name = tableName,
Column_Name = columnName,
Primary_Key = keyData,
Old_Value = string.Empty,
New_Value = newValue
};
this.Changes.Add(log);
}
}
else if (entry.State == EntityState.Modified)
{
PropertyValues currentValues = entry.CurrentValues;
PropertyValues originalValues = entry.OriginalValues;
for (int i = 0; i < currentValues.Properties.Count; i++)
{
string columnName = currentValues.Properties[i].Relational().ColumnName;
string oldValue = entry.GetDatabaseValues().GetValue<object>(originalValues.Properties[i].Name) != null ? entry.GetDatabaseValues().GetValue<object>(originalValues.Properties[i].Name).ToString() : string.Empty;
string newValue = currentValues[currentValues.Properties[i].Name] != null ? currentValues[currentValues.Properties[i].Name].ToString() : string.Empty;
if (oldValue != newValue)
{
EntityChangeModel log = new EntityChangeModel()
{
Change_Type = "CHANGE",
Change_Date = DateTime.Now,
Change_User_ID = 0,
Table_Name = tableName,
Column_Name = columnName,
Primary_Key = keyData,
Old_Value = oldValue,
New_Value = newValue
};
this.Changes.Add(log);
}
}
}
else if (entry.State == EntityState.Deleted)
{
PropertyValues originalValues = entry.OriginalValues;
for (int i = 0; i < originalValues.Properties.Count; i++)
{
string columnName = originalValues.Properties[i].Relational().ColumnName;
string oldValue = entry.GetDatabaseValues().GetValue<object>(originalValues.Properties[i].Name) != null ? entry.GetDatabaseValues().GetValue<object>(originalValues.Properties[i].Name).ToString() : string.Empty;
EntityChangeModel log = new EntityChangeModel()
{
Change_Type = "DELETE",
Change_Date = DateTime.Now,
Change_User_ID = 0,
Table_Name = tableName,
Column_Name = columnName,
Primary_Key = keyData,
Old_Value = oldValue,
New_Value = string.Empty
};
this.Changes.Add(log);
}
}
}
return base.SaveChanges();
}

How to convert ExpressionList of specific type to generic

I am trying to create a method which will be return a Generic Expression List.
In between based on some condition i am creating ExpressionList of specific type and at the end i want to convert that ExpressionList to generic ExpressionList. But, unfortunately i have stuck in conversion.
Below is the code snipet.
I am trying to create a method which will be return a Generic Expression List.
In between based on some condition i am creating ExpressionList of specific type and at the end i want to convert that ExpressionList to generic ExpressionList. But, unfortunately i have stuck in conversion.
Below is the code snipet.
public static <T> ExpressionList<T> generateTransactionList(Map<String,String[]> params, Party party){
String filter = "";
Date startDate = new Date(params.get("startDate")[0]);
Date endDate = new Date(params.get("endDate")[0]+" 23:59:59");
//endDate.setDate(endDate.getDate() + 1);
ExpressionList<TypeOne> TypeOneExpressionList = null;
ExpressionList<TypeTwo> TypeTwoResponseExpressionList = null;
if(settleState == 3) {
TypeTwoResponseExpressionList = TypeTwo.find.select("*").where()
.between("response_date", startDate, endDate)
.eq("status", "failed");
}
else {
acquiringTransactionExpressionList = AcquiringTransaction.find.select("*").where()
.between("transactionTime", startDate, endDate)
.ne("acquiringTransactionStatusType.id", 99);
}
ExpressionList<T> returningTypeOneExpressionList = null;
Class<T> convert = null;
if(TypeOneExpressionList != null) {
TypeOneExpressionList.orderBy("id desc" );
Iterator<TypeOne> iterator = TypeOneExpressionList.findIterate();
while(iterator.hasNext()) {
returningTypeOneExpressionList.add((Expression) convert.cast(iterator.next()));
}
}
else {
TypeTwoResponseExpressionList.orderBy("id desc" );
Iterator<TypeTwo> iterator = TypeTwoResponseExpressionList.findIterate();
while(iterator.hasNext()) {
returningTypeOneExpressionList.add((Expression) convert.cast(iterator.next()));
}
}
return returningTypeOneExpressionList;
}
Thanks in advance.
I found the answer and its really my bad of not trying this earlier.
I just made below changes in the code.
public static <T> ExpressionList<T> generateTransactionList(Map<String,String[]> params, Party party){
String filter = "";
Date startDate = new Date(params.get("startDate")[0]);
Date endDate = new Date(params.get("endDate")[0]+" 23:59:59");
//endDate.setDate(endDate.getDate() + 1);
ExpressionList<TypeOne> TypeOneExpressionList = null;
ExpressionList<TypeTwo> TypeTwoResponseExpressionList = null;
if(settleState == 3) {
TypeTwoResponseExpressionList = TypeTwo.find.select("*").where()
.between("response_date", startDate, endDate)
.eq("status", "failed");
}
else {
acquiringTransactionExpressionList = AcquiringTransaction.find.select("*").where()
.between("transactionTime", startDate, endDate)
.ne("acquiringTransactionStatusType.id", 99);
}
ExpressionList<T> returningAcquiringTransactionExpressionList = null;
Class<T> convert = null;
if(acquiringTransactionExpressionList != null) {
acquiringTransactionExpressionList.orderBy("id desc" );
returningAcquiringTransactionExpressionList = (ExpressionList<T>) acquiringTransactionExpressionList;
}
else {
acquiringTransactionResponseExpressionList.orderBy("id desc" );
returningAcquiringTransactionExpressionList = (ExpressionList<T>) acquiringTransactionResponseExpressionList;
}
return returningTypeOneExpressionList;
}

Data does not get. linq + predicate

I write a extension. This extension a filtering mechanism is turning predicate object. But, I have a problem.
public static IQueryable<T> Filter<T>(this IQueryable<T> data, FilterGroupExpression filter)
{
var source = data;
Expression<Func<T, bool>> predicate;
if (filter.Operator == FilterGroupOperators.And)
predicate = PredicateBuilder.True<T>();
else
predicate = PredicateBuilder.False<T>();
foreach (FilterRuleDescriptive ruleExp in filter.Rules)
{
if (filter.Operator == FilterGroupOperators.And)
predicate = predicate.And<T>(MakeExpression<T>(ruleExp));
else
predicate = predicate.Or<T>(MakeExpression<T>(ruleExp));
}
foreach (FilterGroupExpression groupExp in filter.Groups)
{
if (filter.Operator == FilterGroupOperators.And)
predicate = predicate.And<T>(SubGroupFilter<T>(groupExp));
else
predicate = predicate.Or<T>(SubGroupFilter<T>(groupExp));
}
return source.Where(predicate);
}
public static Expression<Func<T, bool>> SubGroupFilter<T>(FilterGroupExpression filter)
{
Expression<Func<T, bool>> predicate;
if (filter.Operator == FilterGroupOperators.And)
predicate = PredicateBuilder.True<T>();
else
predicate = PredicateBuilder.False<T>();
foreach (FilterRuleDescriptive ruleExp in filter.Rules)
{
if (filter.Operator == FilterGroupOperators.And)
predicate = predicate.And<T>(MakeExpression<T>(ruleExp));
else
predicate = predicate.Or<T>(MakeExpression<T>(ruleExp));
}
foreach (FilterGroupExpression groupExp in filter.Groups)
{
predicate = SubGroupFilter<T>(groupExp);
}
return predicate;
}
public static Expression<Func<T, bool>> MakeExpression<T>(FilterRuleDescriptive condition)
{
Expression currentExpr = null;
var param = Expression.Parameter(typeof(T), "param");
var prop = Expression.Property(param, condition.Field);
var propType = Nullable.GetUnderlyingType(prop.Type) ?? prop.Type;
ConstantExpression constant = null;
condition.Value = Convert.ChangeType(condition.Value, propType);
if (IsNullableType(prop.Type))
constant = Expression.Constant(condition.Value.ConvertToNullable<int>(), prop.Type);
else
constant = Expression.Constant(condition.Value, propType);
if (condition.Value.GetType() == typeof(string))
condition.Value = condition.Value.ToString().Replace("'", string.Empty);
switch (condition.Operator)
{
case FilterRuleOperator.Equals:
currentExpr = Expression.Equal(prop, constant);
break;
case FilterRuleOperator.DoesNotEqual:
currentExpr = Expression.NotEqual(prop, constant);
break;
case FilterRuleOperator.StartsWith:
currentExpr = Expression.Call(prop, typeof(string).GetMethod("StartsWith", new[] { typeof(string) }), constant);
break;
case FilterRuleOperator.EndsWith:
currentExpr = Expression.Call(prop, typeof(string).GetMethod("EndsWith", new[] { typeof(string) }), constant);
break;
case FilterRuleOperator.Contains:
currentExpr = Expression.Call(prop, typeof(string).GetMethod("Contains", new[] { typeof(string) }), constant);
break;
case FilterRuleOperator.IsGreaterThan:
currentExpr = Expression.GreaterThan(prop, constant);
break;
case FilterRuleOperator.IsGreaterThanOrEqual:
currentExpr = Expression.GreaterThanOrEqual(prop, constant);
break;
case FilterRuleOperator.IsLessThan:
currentExpr = Expression.LessThan(prop, constant);
break;
case FilterRuleOperator.IsLessThanOrEqual:
currentExpr = Expression.LessThanOrEqual(prop, constant);
break;
case FilterRuleOperator.IsNull:
currentExpr = Expression.Equal(prop, constant);
break;
case FilterRuleOperator.IsNotNull:
currentExpr = Expression.NotEqual(prop, constant);
break;
default:
throw new ArgumentOutOfRangeException();
}
return Expression.Lambda<Func<T, bool>>(currentExpr, param);
}
source.Where(predicate) returned:
SELECT [t0].[Id], [t0].[Name], [t0].[SmallDescription], [t0].[Description], [t0].[Barcode], [t0].[CategoryId], [t0].[Code], [t0].[PurchasePrice], [t0].[Price], [t0].[OldPrice], [t0].[VatRatio], [t0].[MetaDescription], [t0].[MetaKeywords], [t0].[VariantFirstTypeId], [t0].[VariantSecondTypeId], [t0].[MarkId], [t0].[Mark], [t0].[Stok], [t0].[ShowCase], [t0].[Firm], [t0].[IsVariant], [t0].[IsValid], [t0].[IsSale] FROM [dbo].[Product] AS [t0] WHERE ([t0].[Code] LIKE #p0) AND ([t0].[Name] LIKE #p1) AND ([t0].[Price] >= #p2) AND ([t0].[Price] < #p3) AND (([t0].[SmallDescription] LIKE #p4) OR ([t0].[SmallDescription] LIKE #p5))
No problems so far.
this generated SQL query, the MS SQL Query Editor turns 24 data when I say run. This is an accurate result.
But,
var result = source.Where(predicate);
When questioned by LinQ, 0 turns data.
result.Count() = 0
What could be the problem?
Help me please... :(

Generic Orderby LINQ

I have a generic repository method to enable server side paging:
public virtual IEnumerable<T> GetList(out int totalPages, Expression<Func<T, bool>> filter = null,
Expression<Func<T, object>> orderby = null,
bool ascending = true,
string includeProperties = "",
int pageSize = 10, int pageNumber = 1)
{
IQueryable<T> query = c.Set<T>();
if (filter != null)
{
query = query.Where(filter);
}
query = includeProperties.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Aggregate(query, (current, includeProp) => current.Include(includeProp));
if (orderby != null)
{
query = #ascending ? query.OrderBy(#orderby) : query.OrderByDescending(#orderby);
}
else
{
query = #ascending ? query.OrderBy(o => o.Id) : query.OrderByDescending(o => o.Id);
}
//totalPages = (int) Math.Ceiling((double)(Queryable.Count(query) / pageSize));
totalPages = 1;
if (pageSize > 0)
{
var skip = 0;
var take = pageSize;
if (pageNumber > 1)
{
skip = (pageNumber - 1) * pageSize;
take = pageSize + skip;
}
query = query.Take(take);
query = query.Skip(skip);
}
return query.ToList();
}
T is a base class inherited by my entities
I call this repository method from my service. and i call my service from my controller.
Now from my controller how do i create my orderby expression so that i can pass any column name?
What i've tried so far (found on stackoverflow):
var _OrderByProperty = typeof(Year).GetProperty("Id");
var _OrderByParameter = Expression.Parameter(typeof(Year), "x");
var _OrderByBody = Expression.Property(_OrderByParameter, _OrderByProperty.Name);
var _OrderByConverted = Expression.Convert(_OrderByBody, typeof(Object));
var _OrderByLambda = Expression.Lambda<Func<Year, object>>
(_OrderByConverted, _OrderByParameter);
var list = s.GetList(orderby: _OrderByLambda, totalPages: out totalPages, pageNumber: pageNumber, pageSize: pageSize, ascending: isAsc);
i'm getting the error
Unable to cast the type 'System.Int32' to type 'System.Object'. LINQ to Entities only supports casting EDM primitive or enumeration types.

Create Dynamic LINQ BinaryExpression using data in related tables

I have an application where all queries are created dynamically based on a simple data message received by a WCF service. A data message is, put simply, a collection of columnname/column value pairs, with the addition of an operator, e.g. Equals, Less Than, etc.
Simple Data Message of ColumnName-Value-Operator
Name, Joe, Equals
Age, 35, Less Than
Occupation, Geek, Equals
Rate, 1000, Greater Than
etc...
I have been somewhat successfully using dynamic binary expressions based on the contents of the datamessage.
BinaryExpression expression = null;
ParameterExpression parameter = Expression.Parameter(typeof(MessageType), "p");
foreach (row in DataMessage)
{
BinaryExpression exp = DataLib.MakeQueryFilter(typeof(MessageType),
row.ColumnName,row.ColumnValue,column.DataOperator.ToString(), parameter);
expression = expression == null ? exp : Expression.AndAlso(expression, exp);
results = DataContext.MessageType.Where(Expression.Lambda<Func<Media, bool>>(expression, parameter));
}
public static BinaryExpression MakeQueryFilter(Type type, string propertyName, object value, string dataoperator, ParameterExpression parameter)
{
//var type = oType.GetType();
object queryvalue = null;
var property = type.GetProperty(propertyName);
Type propertyType = property.PropertyType;
if ((propertyType.IsGenericType) && (propertyType.GetGenericTypeDefinition() == typeof(Nullable)))
propertyType = propertyType.GetGenericArguments()[0];
// convert the value appropriately
if (propertyType == typeof(System.Int32))
queryvalue = Convert.ToInt32(value);
if (property.PropertyType == typeof(DateTime))
queryvalue = Convert.ToDateTime(value);
if (property.PropertyType == typeof(Double))
queryvalue = Convert.ToDouble(value);
if (property.PropertyType == typeof(String))
queryvalue = Convert.ToString(value);
if (property.PropertyType == typeof(Guid))
queryvalue = new Guid(value.ToString());
var propertyAccess = Expression.MakeMemberAccess(parameter, property);
var constantValue = Expression.Constant(queryvalue);
Type[] types = new Type[2];
types.SetValue(typeof(Expression), 0);
types.SetValue(typeof(Expression), 1);
var methodInfo = typeof(Expression).GetMethod(dataoperator, types);
var equality2 = (BinaryExpression)methodInfo.Invoke(null, new object[] { propertyAccess, constantValue });
return equality2;
}
The problem I am encountering is when I want to query through a relationship to a value in another table, and even go two->nth relationships deep. Something like this:
Name, Joe, Equals
Age, 35, Less Than
Jobs.Occupation, Geek, Equals
Jobs.Occupation.Salary.Rate, 1000, Greater Than
I have no problem writing the LINQ query by hand:
var results = from m in DataContext.MessageType
where m.Name == "Joe"
& m.Age == 35
& m.Jobs.Occupation == "Geek"
& m.Jobs.Occupation.Salaray.Rate >= 1000
select m;
Any pointers how I can dynamically create this query? Any help is greatly appreciated. Thanks.
Eric S.
Note the use of expanding PropertyAccess.
{
BinaryExpression expression = null;
ParameterExpression parameter = Expression.Parameter(typeof(DataContext.Table), "p");
string columns = "Relation1.Relation2.Column1";
string value = "ABC123";
BinaryExpression exp = MakeQueryFilter(typeof(DataContext.Table), columns,value,'Equal', parameter);
expression = expression == null ? exp : Expression.AndAlso(expression, exp);
results = DataContext.Table.Where(Expression.Lambda<Func<Table, bool>>(expression, parameter));
}
public static BinaryExpression MakeQueryFilter(Type type, string propertyNames, object value, string dataoperator, ParameterExpression parameter)
{
string[] acolumns = columns.Split('.');
var property = typeof (MediaEvent).GetProperty(acolumns[0]);
MemberExpression propertyAccess = Expression.MakeMemberAccess(parameter, property);
Type propertyType = property.PropertyType;
if ((propertyType.IsGenericType) && (propertyType.GetGenericTypeDefinition() == typeof(Nullable)))
propertyType = propertyType.GetGenericArguments()[0];
if (acolumns.Length > 1)
{
for (int i = 1; i < acolumns.Length; i++)
{
propertyAccess = Expression.MakeMemberAccess(propertyAccess, propertyAccess.Type.GetProperty(acolumns[i]));
}
}
object queryvalue = null;
// convert the value appropriately
if (propertyType == typeof(System.Int32))
queryvalue = Convert.ToInt32(value);
if (property.PropertyType == typeof(DateTime))
queryvalue = Convert.ToDateTime(value);
if (property.PropertyType == typeof(Double))
queryvalue = Convert.ToDouble(value);
if (property.PropertyType == typeof(String))
queryvalue = Convert.ToString(value);
if (property.PropertyType == typeof(Guid))
queryvalue = new Guid(value.ToString());
var constantValue = Expression.Constant(queryvalue);
Type[] types = new Type[2];
types.SetValue(typeof(Expression), 0);
types.SetValue(typeof(Expression), 1);
var methodInfo = typeof(Expression).GetMethod(dataoperator, types);
var equality2 = (BinaryExpression)methodInfo.Invoke(null, new object[] { propertyAccess, constantValue });
return equality2;
}
I had the same issue. Thanks for the answer! Very useful!
You wrote this:
caller
{
BinaryExpression expression = null;
ParameterExpression parameter = Expression.Parameter(typeof(DataContext.Table), "p");
string columns = "Relation1.Relation2.Column1";
string value = "ABC123";
BinaryExpression exp
= MakeQueryFilter(typeof(DataContext.Table),
columns,value,'Equal', parameter);
expression = expression == null ? exp : Expression.AndAlso(expression, exp);
results = DataContext.Table.Where(
Expression.Lambda<Func<Table, bool>>(expression, parameter));
}
public static BinaryExpression MakeQueryFilter(Type type, string propertyNames, object value, string dataoperator, ParameterExpression parameter)
{
string[] acolumns = columns.Split('.');
var property = typeof (MediaEvent).GetProperty(acolumns[0]);
MemberExpression propertyAccess = Expression.MakeMemberAccess(parameter, property);
Type propertyType = property.PropertyType;
if ((propertyType.IsGenericType) && (propertyType.GetGenericTypeDefinition() == typeof(Nullable)))
propertyType = propertyType.GetGenericArguments()[0];
if (acolumns.Length > 1)
{
for (int i = 1; i < acolumns.Length; i++)
{
propertyAccess = Expression.MakeMemberAccess(propertyAccess, propertyAccess.Type.GetProperty(acolumns[i]));
}
}
object queryvalue = null;
// convert the value appropriately
if (propertyType == typeof(System.Int32))
queryvalue = Convert.ToInt32(value);
if (property.PropertyType == typeof(DateTime))
queryvalue = Convert.ToDateTime(value);
if (property.PropertyType == typeof(Double))
queryvalue = Convert.ToDouble(value);
if (property.PropertyType == typeof(String))
queryvalue = Convert.ToString(value);
if (property.PropertyType == typeof(Guid))
queryvalue = new Guid(value.ToString());
var constantValue = Expression.Constant(queryvalue);
Type[] types = new Type[2];
types.SetValue(typeof(Expression), 0);
types.SetValue(typeof(Expression), 1);
var methodInfo = typeof(Expression).GetMethod(dataoperator, types);
var equality2 = (BinaryExpression)methodInfo.Invoke(null, new object[] { propertyAccess, constantValue });
return equality2;
}
Maybe better if you write this:
public static BinaryExpression MakeQueryFilter<T>(string propertyNames, object value, string dataoperator, ParameterExpression parameter) where T : class
{
string[] props = propertyNames.Split('.');
var property = typeof(T).GetProperty(props[0]);
MemberExpression propertyAccess = Expression.MakeMemberAccess(parameter, property);
if (props.Length > 1)
{
for (int i = 1; i < props.Length; i++)
{
property = propertyAccess.Type.GetProperty(props[i]);
propertyAccess = Expression.MakeMemberAccess(propertyAccess, property);
}
}
Type propertyType = property.PropertyType;
if ((propertyType.IsGenericType) && (propertyType.GetGenericTypeDefinition() == typeof(Nullable)))
propertyType = propertyType.GetGenericArguments()[0];
object queryvalue = null;
// convert the value appropriately
if (propertyType == typeof(System.Int32))
queryvalue = Convert.ToInt32(value);
if (property.PropertyType == typeof(DateTime))
queryvalue = Convert.ToDateTime(value);
if (property.PropertyType == typeof(Double))
queryvalue = Convert.ToDouble(value);
if (property.PropertyType == typeof(String))
queryvalue = Convert.ToString(value);
if (property.PropertyType == typeof(Guid))
queryvalue = new Guid(value.ToString());
var constantValue = Expression.Constant(queryvalue);
Type[] types = new Type[2];
types.SetValue(typeof(Expression), 0);
types.SetValue(typeof(Expression), 1);
var methodInfo = typeof(Expression).GetMethod(dataoperator, types);
var equality2 = (BinaryExpression)methodInfo.Invoke(null, new object[] { propertyAccess, constantValue });
return equality2;
}

Resources