How to translate Linq Expression where clause to hql where clause? - linq

For some reason, I need to combine Linq Expression (only where clause) & an HQL where clause into one query.
I find that the session.Query<T>() API will translate Linq Expression to a HqlQuery object (that extends HqlExpression).
How can I translate the Linq Expression where clause to an HQL where clause queryString, and then I can combine another HQL where clause queryString into a new query?

Seems that is not possible to use exists NHibernate API to convert Linq expression to HQL tree.
The HQL tree produced from the Linq expression is not reversable to an actual HQL query.
So I have to translate Linq expression to HQL by self:
var expr = GetExpr<Ninja>(x =>
x.Age > 1 && x.Country.Name == "中国"
||
(x.Id > 10 && x.Country.Name == "中国")
);
var translator = new ExpressionToHqlTranslator("_this");
translator.Translate(expr);
Console.WriteLine(translator.WhereClause);
Console.WriteLine(translator.Patameters);
============== result =============
WhereClause: (((_this.Age > ?) AND (_this.Country.Name = ?)) OR ((_this.Id > ?) AND (_this.Country.Name = ?)))
Patameters:4
=============== the critical code =============
static Expression<Func<T, object>> GetExpr<T>(Expression<Func<T, object>> expr){
eturn expr;
}
using System;
using System.Linq;
using NHibernate.Linq;
using NHibernate.Linq.Visitors;
using System.Linq.Expressions;
using NHibernate;
using System.Text;
using System.Collections.Generic;
namespace Rhythm.Linq
{
public class ExpressionToHqlTranslator : System.Linq.Expressions.ExpressionVisitor
{
private StringBuilder sb;
private string _orderBy = "";
private int? _skip = null;
private int? _take = null;
private string _whereClause = "";
List<object> patameters;
public int? Skip
{
get
{
return _skip;
}
}
public int? Take
{
get
{
return _take;
}
}
public string OrderBy
{
get
{
return _orderBy;
}
}
public string WhereClause
{
get
{
return _whereClause;
}
}
public List<object> Patameters
{
get
{
return patameters;
}
set
{
patameters = value;
}
}
string prefix;
public ExpressionToHqlTranslator(string prefix = null)
{
this.prefix = string.IsNullOrEmpty(prefix) ? null : (prefix + ".");
}
public string Translate(Expression expression)
{
this.sb = new StringBuilder();
this.patameters = new List<object>();
this.Visit(expression);
_whereClause = this.sb.ToString();
return _whereClause;
}
private static Expression StripQuotes(Expression e)
{
while (e.NodeType == ExpressionType.Quote)
{
e = ((UnaryExpression)e).Operand;
}
return e;
}
protected override Expression VisitMethodCall(MethodCallExpression m)
{
if (m.Method.DeclaringType == typeof(Queryable) && m.Method.Name == "Where")
{
this.Visit(m.Arguments[0]);
LambdaExpression lambda = (LambdaExpression)StripQuotes(m.Arguments[1]);
this.Visit(lambda.Body);
return m;
}
else if (m.Method.Name == "Take")
{
if (this.ParseTakeExpression(m))
{
Expression nextExpression = m.Arguments[0];
return this.Visit(nextExpression);
}
}
else if (m.Method.Name == "Skip")
{
if (this.ParseSkipExpression(m))
{
Expression nextExpression = m.Arguments[0];
return this.Visit(nextExpression);
}
}
else if (m.Method.Name == "OrderBy")
{
if (this.ParseOrderByExpression(m, "ASC"))
{
Expression nextExpression = m.Arguments[0];
return this.Visit(nextExpression);
}
}
else if (m.Method.Name == "OrderByDescending")
{
if (this.ParseOrderByExpression(m, "DESC"))
{
Expression nextExpression = m.Arguments[0];
return this.Visit(nextExpression);
}
}
throw new NotSupportedException(string.Format("The method '{0}' is not supported", m.Method.Name));
}
protected override Expression VisitUnary(UnaryExpression u)
{
switch (u.NodeType)
{
case ExpressionType.Not:
sb.Append(" NOT ");
this.Visit(u.Operand);
break;
case ExpressionType.Convert:
this.Visit(u.Operand);
break;
default:
throw new NotSupportedException(string.Format("The unary operator '{0}' is not supported", u.NodeType));
}
return u;
}
/// <summary>
///
/// </summary>
/// <param name="b"></param>
/// <returns></returns>
protected override Expression VisitBinary(BinaryExpression b)
{
sb.Append("(");
this.Visit(b.Left);
switch (b.NodeType)
{
case ExpressionType.And:
sb.Append(" AND ");
break;
case ExpressionType.AndAlso:
sb.Append(" AND ");
break;
case ExpressionType.Or:
sb.Append(" OR ");
break;
case ExpressionType.OrElse:
sb.Append(" OR ");
break;
case ExpressionType.Equal:
if (IsNullConstant(b.Right))
{
sb.Append(" IS ");
}
else
{
sb.Append(" = ");
}
break;
case ExpressionType.NotEqual:
if (IsNullConstant(b.Right))
{
sb.Append(" IS NOT ");
}
else
{
sb.Append(" <> ");
}
break;
case ExpressionType.LessThan:
sb.Append(" < ");
break;
case ExpressionType.LessThanOrEqual:
sb.Append(" <= ");
break;
case ExpressionType.GreaterThan:
sb.Append(" > ");
break;
case ExpressionType.GreaterThanOrEqual:
sb.Append(" >= ");
break;
default:
throw new NotSupportedException(string.Format("The binary operator '{0}' is not supported", b.NodeType));
}
this.Visit(b.Right);
sb.Append(")");
return b;
}
protected override Expression VisitConstant(ConstantExpression c)
{
this.patameters.Add(c.Value);
sb.Append('?');
//IQueryable q = c.Value as IQueryable;
//if (q == null && c.Value == null)
//{
// sb.Append("NULL");
//}
//else if (q == null)
//{
// switch (Type.GetTypeCode(c.Value.GetType()))
// {
// case TypeCode.Boolean:
// sb.Append(((bool)c.Value) ? 1 : 0);
// break;
// case TypeCode.String:
// sb.Append("'");
// sb.Append(c.Value);
// sb.Append("'");
// break;
// case TypeCode.DateTime:
// sb.Append("'");
// sb.Append(c.Value);
// sb.Append("'");
// break;
// case TypeCode.Object:
// throw new NotSupportedException(string.Format("The constant for '{0}' is not supported", c.Value));
// default:
// sb.Append(c.Value);
// break;
// }
//}
return c;
}
protected override Expression VisitMember(MemberExpression m)
{
if (this.prefix != null)
{
sb.Append(this.prefix);
}
sb.Append(ContactModelPropertyVistHierarchyExpression(m, m.Member.DeclaringType));
//if (m.Expression != null && m.Expression.NodeType == ExpressionType.Parameter)
//{
// sb.Append(m.Member.Name);
// return m;
//}
return m;
//throw new NotSupportedException(string.Format("The member '{0}' is not supported", m.Member.Name));
}
protected bool IsNullConstant(Expression exp)
{
return (exp.NodeType == ExpressionType.Constant && ((ConstantExpression)exp).Value == null);
}
private bool ParseOrderByExpression(MethodCallExpression expression, string order)
{
UnaryExpression unary = (UnaryExpression)expression.Arguments[1];
LambdaExpression lambdaExpression = (LambdaExpression)unary.Operand;
lambdaExpression = (LambdaExpression)NHibernate.Linq.Visitors.Evaluator.PartialEval(lambdaExpression);
MemberExpression body = lambdaExpression.Body as MemberExpression;
if (body != null)
{
if (string.IsNullOrEmpty(_orderBy))
{
_orderBy = string.Format("{0} {1}", body.Member.Name, order);
}
else
{
_orderBy = string.Format("{0}, {1} {2}", _orderBy, body.Member.Name, order);
}
return true;
}
return false;
}
private bool ParseTakeExpression(MethodCallExpression expression)
{
ConstantExpression sizeExpression = (ConstantExpression)expression.Arguments[1];
int size;
if (int.TryParse(sizeExpression.Value.ToString(), out size))
{
_take = size;
return true;
}
return false;
}
private bool ParseSkipExpression(MethodCallExpression expression)
{
ConstantExpression sizeExpression = (ConstantExpression)expression.Arguments[1];
int size;
if (int.TryParse(sizeExpression.Value.ToString(), out size))
{
_skip = size;
return true;
}
return false;
}
}
public static string ContactModelPropertyVistHierarchyExpression(Expression expr, Type modelType)
{
StringBuilder sb = new StringBuilder();
Expression curr = expr;
// TypedParameterExpression
while (curr != null)
{
if (curr is MemberExpression)
{
var x = curr as MemberExpression;
sb.Insert(0, x.Member.Name);
curr = x.Expression;
}
else if (curr is MethodCallExpression)
{
var x = curr as MethodCallExpression;
sb.Insert(0, x.Method.Name);
curr = x.Object;
}
else if (curr is ParameterExpression)
{
break;
}
else
{
throw new ArgumentException("Unsupported Expression type " + curr.GetType().FullName + " for expression " + expr.ToString(), "expr");
}
sb.Insert(0, '.');
}
return sb.Length > 1 ? sb.Remove(0, 1).ToString() : sb.ToString();
}
}
add dll reference NHibernate.Linq.dll

Related

Dynamics crm + how to get attribute value based on the type dynamically in plugin code

I have the below requirement.
I need to perform the sum of each field across multiple records of the same entity However while performing the sum, I also need to check the type and cast them accrodingly. For eg, For whole number cast to Int, For Decimal cast to decimal. Also some of the values are aliased value too. I am looking for a generic function which I can call for both alias fields and direct fields and it will return me the value based on the type
Background on the code written below -
Attribute List is the list of all attributes that belong to the
entity.
Format in which the field values are stored in AttributeList-
AttributeList = { "price ", "quantity", "contact.revenue", "opportunity.sales"}
price, quantity - fields of main entity on which we are querying
contact.revenue, opportunity.sales - fields of the aliased entities,
entity name is appended to understand which entity's field it is
Below is the code which i have tried so far -
I only have decimal and whole number fields in my attributeList.
private void calculate(List<string> attributeList,List<Entity> mainEntityList,Guid targetId,Guid oppId,Guid contactId)
{
var mainentity = new mainEntity();
mainentity.Id = targetId;
var opportunity = new Opportunity();
opportunity.Id = oppId;
var contact = new Contact();
contact.Id = contactId;
foreach (var attribute in attributeList)
{
var fieldSum = new decimal(0);
int intFieldSum = 0;
bool attributeFound = false;
foreach (var entity in mainEntityList)
{
if (entity.Contains(attribute))
{
var type = entity[attribute].GetType().Name;
attributeFound = true;
switch (type)
{
case "AliasedValue":
var aliasedFieldValue = entity.GetAttributeValue<AliasedValue>(attribute);
if (aliasedFieldValue.Value.GetType().Name == "Decimal")
{
decimalFieldSum += (decimal)aliasedFieldValue.Value;
}
else
{
intFieldSum += (int)aliasedFieldValue.Value;
}
break;
case "Decimal":
decimalFieldSum += entity.GetAttributeValue<decimal>(attribute);
break;
case "Int32":
intFieldSum += entity.GetAttributeValue<int>(attribute);
break;
default:
break;
}
}
}
if (attributeFound)
{
if (attribute.Contains("opportunity"))
{
opportunity[attribute] = decimalFieldSum != 0 ? decimalFieldSum : intFieldSum;
}
else if (attribute.Contains("contact"))
{
contact[attribute] = decimalFieldSum != 0 ? decimalFieldSum : intFieldSum;
}
else
{
mainentity[attribute] = decimalFieldSum != 0 ? decimalFieldSum : intFieldSum;
}
}
}
service.update(opportunity);
service.update(contact);
service.update(mainentity);
}
Any help would be appreciated.
Just a little bit edited your code.
...
var fieldSum = new decimal(0);
foreach (var entity in mainEntityList)
{
fieldSum += GetAttrValue(entity, attribute);
}
...
You can use this function to calculate fieldSum variable which is of decimal type.
private decimal GetAttrValue(Entity entity, string attribute)
{
var attrValue = new decimal(0);
if (!entity.Contains(attribute) || entity.Attributes[attribute] == null)
{
return attrValue;
}
var type = entity.Attributes[attribute].GetType().Name;
switch (type)
{
case "AliasedValue":
var aliasedFieldValue = entity.GetAttributeValue<AliasedValue>(attribute);
attrValue = type == "Decimal" ? (decimal)aliasedFieldValue.Value : (int)aliasedFieldValue.Value;
break;
case "Decimal":
attrValue = entity.GetAttributeValue<decimal>(attribute);
break;
case "Int32":
attrValue = entity.GetAttributeValue<int>(attribute);
break;
default:
break;
}
return attrValue;
}
On the other hand if you just need a generic function which will return decimal or int value for an attribute you can use this
private T GetAttrValue<T>(Entity entity, string attribute)
{
if (!entity.Contains(attribute) || entity.Attributes[attribute] == null)
{
return default(T);
}
T result;
var type = entity.Attributes[attribute].GetType().Name;
if (type == "AliasedValue")
{
var aliasedFieldValue = entity.GetAttributeValue<AliasedValue>(attribute);
result = (T)aliasedFieldValue.Value;
}
else
{
result = entity.GetAttributeValue<T>(attribute);
}
return result;
}
--Update--
So, here is the whole code if I understand you requirements right.
First of all add this class.
public class AttributeInfo
{
public string Name { get; set; }
public Type Type { get; set; }
public decimal DecimalSum { get; set; } = new decimal(0);
public int IntSum { get; set; } = 0;
}
And add this function
private void SetValue(Entity entity, AttributeInfo attributeInfo)
{
if (entity.Contains(attributeInfo.Name))
{
switch (attributeInfo.Type.Name)
{
case "Decimal":
entity[attributeInfo.Name] = attributeInfo.DecimalSum;
break;
case "Int32":
entity[attributeInfo.Name] = attributeInfo.IntSum;
break;
default:
break;
}
}
}
Then this is you Calculate function
private void Calculate(List<string> attributeList, List<Entity> mainEntityList, Guid targetId, Guid oppId, Guid contactId)
{
var mainentity = new mainEntity();
mainentity.Id = targetId;
var opportunity = new Opportunity();
opportunity.Id = oppId;
var contact = new Contact();
contact.Id = contactId;
var attributesInfo = new List<AttributeInfo>();
foreach (var attribute in attributeList)
{
var attributeInfo = new AttributeInfo
{
Name = attribute
};
foreach (var entity in mainEntityList)
{
if (entity.Contains(attribute))
{
attributeInfo.Type = entity[attribute].GetType();
switch (attributeInfo.Type.Name)
{
case "AliasedValue":
var aliasedFieldValue = entity.GetAttributeValue<AliasedValue>(attribute);
if (aliasedFieldValue.Value.GetType().Name == "Decimal")
{
attributeInfo.DecimalSum += (decimal)aliasedFieldValue.Value;
}
else
{
attributeInfo.IntSum += (int)aliasedFieldValue.Value;
}
break;
case "Decimal":
attributeInfo.DecimalSum += entity.GetAttributeValue<decimal>(attribute);
break;
case "Int32":
attributeInfo.IntSum += entity.GetAttributeValue<int>(attribute);
break;
default:
break;
}
}
}
attributesInfo.Add(attributeInfo);
}
foreach (var attributeInfo in attributesInfo)
{
if (attributeInfo.Type != null)
{
SetValue(mainentity, attributeInfo);
SetValue(opportunity, attributeInfo);
SetValue(contact, attributeInfo);
}
}
service.update(mainentity);
service.update(opportunity);
service.update(contact);
}
I should say that the structure of the calculate function still seems weird for me. However, here I tried to keep the main structure.

Are there any Dart resources that would split a command-line String into a List<String> of arguments?

Are there any Dart resources that would split a command-line String into a List<String> of arguments?
ArgsParser takes a List<String> of already split arguments usually from main(List<String>).
To answer my own question,
I've converted a Java function I liked into a Dart Converter<String, List<String>) class:
import 'dart:convert';
/// Splits a `String` into a list of command-line argument parts.
/// e.g. "command -p param" -> ["command", "-p", "param"]
///
class CommandlineConverter extends Converter<String, List<String>>
{
#override
List<String> convert(String input)
{
if (input == null || input.isEmpty)
{
//no command? no string
return [];
}
final List<String> result = new List<String>();
var current = "";
String inQuote;
bool lastTokenHasBeenQuoted = false;
for (int index = 0; index < input.length; index++)
{
final token = input[index];
if (inQuote != null)
{
if (token == inQuote)
{
lastTokenHasBeenQuoted = true;
inQuote = null;
}
else
{
current += token;
}
}
else
{
switch (token)
{
case "'": // '
case '"': // ""
inQuote = token;
continue;
case " ": // space
if (lastTokenHasBeenQuoted || current.isNotEmpty)
{
result.add(current);
current = "";
}
break;
default:
current += token;
lastTokenHasBeenQuoted = false;
}
}
}
if (lastTokenHasBeenQuoted || current.isNotEmpty)
{
result.add(current);
}
if (inQuote != null)
{
throw new Exception("Unbalanced quote $inQuote in input:\n$input");
}
return result;
}
}

LINQ PredicateBuilder not work in my dynamic search

I have a book table in my database and I have book view named vwShared in my edmx. I want to create dynamic search with operators for user to find books. I have 2 SearchColumns dropdownlist contains "Title, Authors, Published Year, Subject". I have 2 SearchType dropdownlist contains "StartsWith, Contains, EndsWith, Equals". I have another dropdownlist contains "AND, OR" to combine 2 search results. The following is my code.
var predicate = PredicateBuilder.True<DataLayer.vwShared>();
if (joinOperator == "AND")
{
if (SearchColumn1 == "Title" && SearchType1 == "Contains")
predicate = predicate.And(e1 => e1.Title.Contains(txtSearch1.Text));
if (SearchColumn2 == "Authors" && SearchType2 == "Contains")
predicate = predicate.And(e1 => e1.Authors.Contains(txtSearch2.Text));
}
else if (joinOperator == "OR")
{
if (SearchColumn1 == "Title" && SearchType1 == "Contains")
predicate = predicate.Or(e1 => e1.Title.Contains(txtSearch1.Text));
if (SearchColumn2 == "Authors" && SearchType2 == "Contains")
predicate = predicate.Or(e1 => e1.Authors.Contains(txtSearch2.Text));
}
List<DataLayer.vwShared> bookList= new DataLayer.Solib_DMREntities().SP_SharedData_GetAll("AllLocal").ToList<DataLayer.vwShared>();
var bookList= from books in bookList.AsQueryable().Where(predicate)
select books ;
gvBooks.DataSource = bookList.ToList();
gvBooks.DataBind();
The above code not return proper results. Is there something wrong. ?
The following is my references website.
http://www.albahari.com/nutshell/predicatebuilder.aspx
Please give me advice.
Thanks.
Answering your concrete question. The problem is in the branch for building OR predicate, in which case you should start with PredicateBuilder.False, otherwice there will not be filtering at all (as we know from the school, true or something is always true :)
// ...
else if (joinOperator == "OR")
{
predicate = PredicateBuilder.False<DataLayer.vwShared>();
// ...
}
// ...
step 1:Model
public class Person
{
public int PersonId { get; set; }
public int? Age { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int? Salary { get; set; }
}
public class PersonDBContext : DbContext
{
public virtual DbSet<Person> People { get; set; }
}
step 2 : controller
public class PersonController
{
PersonDBContext db = new PersonDBContext();
public void Add(Person person)
{
db.People.Add(person);
db.SaveChanges();
}
public List<Person> GetAll()
{
return db.People.ToList();
}
public List<Person> GetByPredicateValue(Expression<Func<Person, bool>> predicate)
{
if (predicate != null)
return db.People.Where(predicate.Compile()).ToList();
else
return null;
}
public List<Person> GetByPredicateAndPersonListValue(List<Person> PeopleList,Expression<Func<Person, bool>> predicate)
{
if (predicate != null)
return PeopleList.Where(predicate.Compile()).ToList();
else
return null;
}
}
step 3: code behind
public partial class MainWindow : Window
{
PersonController pc;
public static List<Person> PeopleFilterList = null;
public static string CurrentColumn = null;
public MainWindow()
{
pc = new PersonController();
InitializeComponent();
grid.ItemsSource = pc.GetAll();
grid.PreviewMouseDown += grid_PreviewMouseDown;
}
void grid_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
TableViewHitInfo hi = ((TableView)grid.View).CalcHitInfo(e.OriginalSource as DependencyObject);
if (hi == null) return;
if (hi.HitTest == TableViewHitTest.ColumnHeader || hi.HitTest == TableViewHitTest.ColumnHeaderFilterButton)
{
grid.UnselectAll();
GridColumn currentColumn = ((DevExpress.Xpf.Grid.GridViewHitInfoBase)(hi)).Column;
CurrentColumn = currentColumn.FieldName;
(grid.View as TableView).SelectCells(0, currentColumn, grid.VisibleRowCount - 1, currentColumn);
}
}
Expression<Func<Person, bool>> _result=null;
string str="";
private void IdForm_ButtonClicked(object sender, IdentityUpdateEventArgs e)
{
_result = e.FirstName;
}
public MainWindow(Expression<Func<Person, bool>> result)
{
Window1 f = new Window1();
f.IdentityUpdated += new Window1.IdentityUpdateHandler(IdForm_ButtonClicked);
pc = new PersonController();
InitializeComponent();
_result = result;
if (PeopleFilterList != null)
PeopleFilterList = pc.GetByPredicateAndPersonListValue(PeopleFilterList,_result).ToList();
else
PeopleFilterList = pc.GetByPredicateValue(_result).ToList();
grid.ItemsSource = PeopleFilterList;
grid.PreviewMouseDown += grid_PreviewMouseDown;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Window1 w1 = new Window1(CurrentColumn);
w1.Show();
}
}
step 4 : Filter code behind
public partial class Window1 : Window
{
public delegate void IdentityUpdateHandler(object sender, IdentityUpdateEventArgs e);
public event IdentityUpdateHandler IdentityUpdated;
string _currentColumn = null;
public Window1()
{
InitializeComponent();
}
public Window1(string currentColumn)
{
_currentColumn = currentColumn;
InitializeComponent();
}
public static Expression<Func<Person, bool>> predicateValue;
IdentityUpdateEventArgs args;
private void Button_Click(object sender, RoutedEventArgs e)
{
string operatorName = "";
if (!String.IsNullOrEmpty(txtSmaller.Text.Trim()))
operatorName = txtSmaller.Name;
else if (!String.IsNullOrEmpty(txtElder.Text.Trim()))
operatorName = txtElder.Name;
else if (!String.IsNullOrEmpty(txtContains.Text.Trim()))
operatorName = txtContains.Name;
else if (!String.IsNullOrEmpty(txtStartWith.Text.Trim()))
operatorName = txtStartWith.Name;
else if (!String.IsNullOrEmpty(txtEqual.Text.Trim()))
operatorName = txtEqual.Name;
else if (!String.IsNullOrEmpty(txtNotEqual.Text.Trim()))
operatorName = txtNotEqual.Name;
else if (!String.IsNullOrEmpty(txtSmallerOrEqual.Text.Trim()))
operatorName = txtSmallerOrEqual.Name;
else if (!String.IsNullOrEmpty(txtElderOrEqual.Text.Trim()))
operatorName = txtElderOrEqual.Name;
else if (!String.IsNullOrEmpty(txtSmallerThan.Text.Trim()) && !String.IsNullOrEmpty(txtBiggerThan.Text.Trim()))
operatorName = txtSmallerThan.Name;
switch (operatorName)
{
case "txtSmaller":
predicateValue = (x => (int)x.GetType().GetProperty(_currentColumn).GetValue(x, null) < Convert.ToInt32(txtSmaller.Text));
break;
case "txtElder":
predicateValue = (x => (int)x.GetType().GetProperty(_currentColumn).GetValue(x, null) > Convert.ToInt32(txtElder.Text));
break;
case "txtSmallerOrEqual":
predicateValue = (x => (int)x.GetType().GetProperty(_currentColumn).GetValue(x, null) <= Convert.ToInt32(txtSmallerOrEqual.Text));
break;
case "txtElderOrEqual":
predicateValue = (x => (int)x.GetType().GetProperty(_currentColumn).GetValue(x, null) >= Convert.ToInt32(txtElderOrEqual.Text));
break;
case "txtEqual":
predicateValue = (x => (int)x.GetType().GetProperty(_currentColumn).GetValue(x, null) == Convert.ToInt32(txtEqual.Text));
break;
case "txtNotEqual":
predicateValue = (x => (int)x.GetType().GetProperty(_currentColumn).GetValue(x, null) != Convert.ToInt32(txtNotEqual.Text));
break;
case "txtSmallerThan":
predicateValue = (x => (int)x.GetType().GetProperty(_currentColumn).GetValue(x, null) >= Convert.ToInt32(txtBiggerThan.Text)
&& (int)x.GetType().GetProperty(_currentColumn).GetValue(x, null) <= Convert.ToInt32(txtSmallerThan.Text));
break;
case "txtStartWith":
predicateValue = (x => x.GetType().GetProperty(_currentColumn).GetValue(x, null).ToString().StartsWith(txtStartWith.Text));
break;
case "txtContains":
predicateValue = (x => x.GetType().GetProperty(_currentColumn).GetValue(x,null).ToString().Contains(txtContains.Text));
break;
}
MainWindow mw = new MainWindow(predicateValue);
mw.Show();
this.Close();
}
void Window1_IdentityUpdated(object sender, IdentityUpdateEventArgs e)
{
e = args;
}
}
public class IdentityUpdateEventArgs : System.EventArgs
{
private Expression<Func<Person, bool>> mFirstName;
public IdentityUpdateEventArgs(Expression<Func<Person, bool>> sFirstName)
{
this.mFirstName = sFirstName;
}
public Expression<Func<Person, bool>> FirstName
{
get
{
return mFirstName;
}
}
}

Converting a linq query or foreach loop into a form that is awaitable

I am trying to convert my method to Async. I cannot seem to grasp converting a linq query or foreach loop into a form that is awaitable. I read here on SO that EntityFramework + Linq don’t mix very well asynchronously. Perhaps that is why I could not find a previous Question that matches my needs exactly. Would someone care to point me in the right direction?
private static async Task<decimal> GetLastPriceAsync(string customer, string stockNumber)
{
Debug.WriteLine("Get Last Price Called");
decimal lastCost = 0;
var lastDate = new DateTime(1900, 1, 1);
if (string.IsNullOrEmpty(customer))
{
Debug.WriteLine("There was no customer");
return 0;
}
Debug.WriteLine("We have a customer");
if (string.IsNullOrEmpty(stockNumber))
{
Debug.WriteLine("There was no item");
return 0;
}
Debug.WriteLine("We have a Part Number");
try
{
IEnumerable<SA_HistoryHeader> orders =
DContext.SA_HistoryHeader.Local.Where(c => c.strCustomer == customer);
if (!orders.Any())
{
Debug.WriteLine("No order found.");
return 0;
}
Debug.WriteLine("We have previous Orders Found");
foreach (SA_HistoryHeader thisOrder in orders)
{
Debug.WriteLine("Looping through orders.");
DateTime date = lastDate;
IEnumerable<SA_HistoryDetail> details = thisOrder.SA_HistoryDetail
.Where(i => i.strStock == stockNumber && i.dteLineDate > date && i.bytLineType == 003);
foreach (
SA_HistoryDetail detail in
details.Where(detail => detail != null && !string.IsNullOrEmpty(detail.strDescription)))
{
if (detail.dteLineDate != null)
{
lastDate = (DateTime) detail.dteLineDate;
}
else
{
Debug.WriteLine("Order Date was null");
}
if (detail.curUnitPrice != null)
{
lastCost = (decimal) detail.curUnitPrice;
}
else
{
Debug.WriteLine("Last Cost was null");
}
}
}
}
catch (Exception ex)
{
Debug.WriteLine("Last Price Calc Error: " + ex.InnerException.Message);
}
return lastCost;
}

EF 4.1, database first and Many-to-Many relationships - How to get all sub-objects?

Let's say I have the following tables in a database forming a Many-to-Many Relationship. And in an ASP.Net MVC project using EF 4.1, I have corresponding POCO entities and a Repository layer to access the database.
People: PersonId PK, Firsname, Lastname
FavoriteRestaurants: ID PK, PersonId, RestaurantId
Restaurants: ResaurantId PK, Name
If I have a PersonId, what is the best way to list all this person's favorite restaurant names?
Or how would I do to initialise this Enumerable based on the person's Id using a repository layer?
IEnumerable MyFavoriteRestaurants = ???
I know I could use foreach to loop on the Person.FavoriteRestaurants collections an retrieve each FavoriteRestaurant.Restaurant one by one, but I was wondering if there were a more elegant way to do this in one line of code.
UPDATE
Here is an example of a Person POCO entity class in my project. This code has been generated by a Microsoft template downloaded from here:
http://visualstudiogallery.msdn.microsoft.com/23df0450-5677-4926-96cc-173d02752313/
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
namespace UpDir.Domain
{
public partial class Person : EntityBase
{
#region Primitive Properties
public virtual int PersonId
{
get;
set;
}
public virtual string Firstname
{
get;
set;
}
public virtual string Middlename
{
get;
set;
}
public virtual string Lastname
{
get;
set;
}
public virtual string Nickname
{
get;
set;
}
public virtual string EncryptedEmail
{
get;
set;
}
public virtual string Photo
{
get;
set;
}
public virtual short StatusId
{
get { return _statusId; }
set
{
if (_statusId != value)
{
if (Status != null && Status.StatusId != value)
{
Status = null;
}
_statusId = value;
}
}
}
private short _statusId;
#endregion
#region Navigation Properties
public virtual ICollection<Member> Members
{
get
{
if (_members == null)
{
var newCollection = new FixupCollection<Member>();
newCollection.CollectionChanged += FixupMembers;
_members = newCollection;
}
return _members;
}
set
{
if (!ReferenceEquals(_members, value))
{
var previousValue = _members as FixupCollection<Member>;
if (previousValue != null)
{
previousValue.CollectionChanged -= FixupMembers;
}
_members = value;
var newValue = value as FixupCollection<Member>;
if (newValue != null)
{
newValue.CollectionChanged += FixupMembers;
}
}
}
}
private ICollection<Member> _members;
public virtual ICollection<Message> Messages
{
get
{
if (_messages == null)
{
var newCollection = new FixupCollection<Message>();
newCollection.CollectionChanged += FixupMessages;
_messages = newCollection;
}
return _messages;
}
set
{
if (!ReferenceEquals(_messages, value))
{
var previousValue = _messages as FixupCollection<Message>;
if (previousValue != null)
{
previousValue.CollectionChanged -= FixupMessages;
}
_messages = value;
var newValue = value as FixupCollection<Message>;
if (newValue != null)
{
newValue.CollectionChanged += FixupMessages;
}
}
}
}
private ICollection<Message> _messages;
public virtual ICollection<Notification> Notifications
{
get
{
if (_notifications == null)
{
var newCollection = new FixupCollection<Notification>();
newCollection.CollectionChanged += FixupNotifications;
_notifications = newCollection;
}
return _notifications;
}
set
{
if (!ReferenceEquals(_notifications, value))
{
var previousValue = _notifications as FixupCollection<Notification>;
if (previousValue != null)
{
previousValue.CollectionChanged -= FixupNotifications;
}
_notifications = value;
var newValue = value as FixupCollection<Notification>;
if (newValue != null)
{
newValue.CollectionChanged += FixupNotifications;
}
}
}
}
private ICollection<Notification> _notifications;
public virtual Status Status
{
get { return _status; }
set
{
if (!ReferenceEquals(_status, value))
{
var previousValue = _status;
_status = value;
FixupStatus(previousValue);
}
}
}
private Status _status;
public virtual ICollection<UpDirEmail> FromEmails
{
get
{
if (_fromEmails == null)
{
var newCollection = new FixupCollection<UpDirEmail>();
newCollection.CollectionChanged += FixupFromEmails;
_fromEmails = newCollection;
}
return _fromEmails;
}
set
{
if (!ReferenceEquals(_fromEmails, value))
{
var previousValue = _fromEmails as FixupCollection<UpDirEmail>;
if (previousValue != null)
{
previousValue.CollectionChanged -= FixupFromEmails;
}
_fromEmails = value;
var newValue = value as FixupCollection<UpDirEmail>;
if (newValue != null)
{
newValue.CollectionChanged += FixupFromEmails;
}
}
}
}
private ICollection<UpDirEmail> _fromEmails;
public virtual ICollection<UpDirEmail> ToEmails
{
get
{
if (_toEmails == null)
{
var newCollection = new FixupCollection<UpDirEmail>();
newCollection.CollectionChanged += FixupToEmails;
_toEmails = newCollection;
}
return _toEmails;
}
set
{
if (!ReferenceEquals(_toEmails, value))
{
var previousValue = _toEmails as FixupCollection<UpDirEmail>;
if (previousValue != null)
{
previousValue.CollectionChanged -= FixupToEmails;
}
_toEmails = value;
var newValue = value as FixupCollection<UpDirEmail>;
if (newValue != null)
{
newValue.CollectionChanged += FixupToEmails;
}
}
}
}
private ICollection<UpDirEmail> _toEmails;
public virtual ICollection<UpDirEvent> UpDirEvents
{
get
{
if (_upDirEvents == null)
{
var newCollection = new FixupCollection<UpDirEvent>();
newCollection.CollectionChanged += FixupUpDirEvents;
_upDirEvents = newCollection;
}
return _upDirEvents;
}
set
{
if (!ReferenceEquals(_upDirEvents, value))
{
var previousValue = _upDirEvents as FixupCollection<UpDirEvent>;
if (previousValue != null)
{
previousValue.CollectionChanged -= FixupUpDirEvents;
}
_upDirEvents = value;
var newValue = value as FixupCollection<UpDirEvent>;
if (newValue != null)
{
newValue.CollectionChanged += FixupUpDirEvents;
}
}
}
}
private ICollection<UpDirEvent> _upDirEvents;
#endregion
#region Association Fixup
private void FixupStatus(Status previousValue)
{
if (previousValue != null && previousValue.People.Contains(this))
{
previousValue.People.Remove(this);
}
if (Status != null)
{
if (!Status.People.Contains(this))
{
Status.People.Add(this);
}
if (StatusId != Status.StatusId)
{
StatusId = Status.StatusId;
}
}
}
private void FixupMembers(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach (Member item in e.NewItems)
{
item.Person = this;
}
}
if (e.OldItems != null)
{
foreach (Member item in e.OldItems)
{
if (ReferenceEquals(item.Person, this))
{
item.Person = null;
}
}
}
}
private void FixupMessages(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach (Message item in e.NewItems)
{
item.Person = this;
}
}
if (e.OldItems != null)
{
foreach (Message item in e.OldItems)
{
if (ReferenceEquals(item.Person, this))
{
item.Person = null;
}
}
}
}
private void FixupNotifications(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach (Notification item in e.NewItems)
{
item.Person = this;
}
}
if (e.OldItems != null)
{
foreach (Notification item in e.OldItems)
{
if (ReferenceEquals(item.Person, this))
{
item.Person = null;
}
}
}
}
private void FixupFromEmails(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach (UpDirEmail item in e.NewItems)
{
item.FromPerson = this;
}
}
if (e.OldItems != null)
{
foreach (UpDirEmail item in e.OldItems)
{
if (ReferenceEquals(item.FromPerson, this))
{
item.FromPerson = null;
}
}
}
}
private void FixupToEmails(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach (UpDirEmail item in e.NewItems)
{
item.ToPerson = this;
}
}
if (e.OldItems != null)
{
foreach (UpDirEmail item in e.OldItems)
{
if (ReferenceEquals(item.ToPerson, this))
{
item.ToPerson = null;
}
}
}
}
private void FixupUpDirEvents(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach (UpDirEvent item in e.NewItems)
{
item.Person = this;
}
}
if (e.OldItems != null)
{
foreach (UpDirEvent item in e.OldItems)
{
if (ReferenceEquals(item.Person, this))
{
item.Person = null;
}
}
}
}
#endregion
}
}
You don't need to think too much about that, EF will do it for you if you have defined your entity classes correct way like this,
Public class Person{
public int PersonId {get;set;}
public string Firsname{get;set;}
....
public virtual IList<Resturent> Resturents {get;set;}
}
Public class Restaurant{
public int ResaurantId {get;set;}
public string Name{get;set;}
....
public virtual IList<Resturent> People{get;set;}
}
Then you can simply access person.Restaurants to get all restaurants.
I finally figured it out. This is how I am doing it:
IEnumerable<Restaurants> MyFavoriteRestaurants = person.FavoriteRestaurants.Select(m => m.Restaurants);

Resources