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

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;
}

Related

Pagination and Sorting - custom sorting of data

I have a problem with sorting data in my project.
Since I implemented pagination I don't know how solve this issue.
Before pagination I fetched whole list of entities and sort it by this class:
public class EntitySorter {
private static final Logger LOG = Logger.getLogger(EntitySorter.class);
public static int sort(String s1, String s2) {
if (StringUtils.isBlank(s1) || StringUtils.isBlank(s2)) {
return -1;
}
if (!s1.contains("/") || !s2.contains("/")) {
return -1;
}
if (s1.substring(s1.lastIndexOf("/") + 1).length() != 4 ||
s2.substring(s2.lastIndexOf("/") + 1).length() != 4) {
return -1;
}
final String year1 = s1.substring(s1.lastIndexOf("/") + 1);
final String year2 = s2.substring(s2.lastIndexOf("/") + 1);
if (!NumberUtils.isDigits(year1) || !NumberUtils.isDigits(year2)) {
return -1;
}
final int result = NumberUtils.toInt(year1) - NumberUtils.toInt(year2);
if (result != 0) {
return result;
}
final String caseNumber1 = s1.substring(0, s1.indexOf("/"));
final String caseNumber2 = s2.substring(0, s2.indexOf("/"));
if (!NumberUtils.isDigits(caseNumber1) && NumberUtils.isDigits(caseNumber2)) {
try {
final int intCaseNumber1 = Integer.parseInt(caseNumber1.replaceAll("[^0-9]", ""));
return intCaseNumber1 - Integer.parseInt(caseNumber2);
} catch (NumberFormatException e) {
LOG.error(e.getMessage(), e);
}
return -1;
}
if (NumberUtils.isDigits(caseNumber1) && !NumberUtils.isDigits(caseNumber2)) {
try {
final int intCaseNumber2 = Integer.parseInt(caseNumber2.replaceAll("[^0-9]", ""));
return Integer.parseInt(caseNumber1) - intCaseNumber2;
} catch (NumberFormatException e) {
LOG.error(e.getMessage(), e);
}
return -1;
}
if (!NumberUtils.isDigits(caseNumber1) && !NumberUtils.isDigits(caseNumber2)) {
try {
final int intCaseNumber1 = Integer.parseInt(caseNumber1.replaceAll("[^0-9]", ""));
final int intCaseNumber2 = Integer.parseInt(caseNumber2.replaceAll("[^0-9]", ""));
return intCaseNumber1 - intCaseNumber2;
} catch (NumberFormatException e) {
LOG.error(e.getMessage(), e);
}
return -1;
}
return NumberUtils.toInt(caseNumber1) - NumberUtils.toInt(caseNumber2);
}
}
Let's take some example:
We have a list of IDs:
101/2021
102/2021
1/2022
86/2020
Correct sorted list is:
1/2022
102/2021
101/2021
86/2020
In database this ID is one column. It's not split to number and year. I tried to use Sort.by() but I didn't make a success. How can I use pagination and keep correct sorting?
For pagination to work optimally, the data should be indexed correctly..
If there is a different representation of the data you can use with one column then it's the best way.
If not then the easy way would just to decompose one column to multiple columns, create a multi column index and sort by these columns + you need to understand if the natural ordering of the columns fits your logic.
The hard way would be to create user defined function and index on it and other solutions, but I would avoid the unnecessary complexity.
Keep it simple!

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.

Action.Picker returns invalid/wrong Uri (How to get path or byte[] from multiple picked gallery img)

I have an forms app where i need to pick "1 to many" images from the phone storage.
For this i use the dependency injection system.
My problem is the somewhere i get an Android.netUri that resolves to a file that do not exist... and to a file name that i have never seen before.
The kicker is that if i pick pictures that was takes within the last couple of hours this code works...
Im am at the end of my hoap, i really hope someone can point me to something that i'm doing wrong.
i start the Picker activity with:
[assembly: Dependency(typeof(ImagePickerService))]
namespace MyApp.Droid
{
public class ImagePickerService : Java.Lang.Object, IImagePickerService
{
public async Task OpenGallery()
{
try
{
var status = await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Storage);
if (status != PermissionStatus.Granted)
{
if (await CrossPermissions.Current.ShouldShowRequestPermissionRationaleAsync(Permission.Storage))
{
Toast.MakeText(CrossCurrentActivity.Current.Activity, "Need Storage permission to access to your photos.", ToastLength.Long).Show();
}
var results = await CrossPermissions.Current.RequestPermissionsAsync(new[] { Permission.Storage });
status = results[Permission.Storage];
}
if (status == PermissionStatus.Granted)
{
Toast.MakeText(CrossCurrentActivity.Current.Activity, "Pick max 20 images", ToastLength.Long).Show();
var imageIntent = new Intent(Intent.ActionPick);
imageIntent.SetType("image/*");
imageIntent.PutExtra(Intent.ExtraAllowMultiple, true);
imageIntent.SetAction(Intent.ActionPick);
CrossCurrentActivity.Current.Activity.StartActivityForResult(Intent.CreateChooser(imageIntent, "Pick pictures"), 100);
}
else if (status != PermissionStatus.Unknown)
{
Toast.MakeText(CrossCurrentActivity.Current.Activity, "Permission Denied. Can not continue, try again.", ToastLength.Long).Show();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
Toast.MakeText(CrossCurrentActivity.Current.Activity, "Error. Can not continue, try again.", ToastLength.Long).Show();
}
}
}
then in my MainActivity.cs i have the OnActivityResult
I have tried to use the ContentResolver.OpenInputStream to get the image bytes with no luck, so this is commented out atm.
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
if (requestCode == OPENGALLERYCODE && resultCode == Result.Ok)
{
List<string> images = new List<string>();
if (data != null)
{
ClipData clipData = data.ClipData;
if (clipData != null)
{
for (int i = 0; i < clipData.ItemCount; i++)
{
ClipData.Item item = clipData.GetItemAt(i);
/*
var stream = ContentResolver.OpenInputStream(item.Uri); //This throws "FileNotFound"
byte[] byteArray;
using (var memoryStream = new MemoryStream())
{
stream.CopyTo(memoryStream);
byteArray = memoryStream.ToArray();
stream.Close();
stream = null;
}
stream = ContentResolver.OpenInputStream(item.Uri);
var exif = new ExifInterface(stream);
stream.Close();
*/
Android.Net.Uri uri = item.Uri;
var path = GetActualPathFromFile(uri);
if (path != null)
{
var tmpImgPath = RotateToOriginalDimention(path);
images.Add(tmpImgPath);
}
}
}
else
{
Android.Net.Uri uri = data.Data;
var path = GetActualPathFromFile(uri);
if (path != null)
{
var tmpImgPath = RotateToOriginalDimention(path);
images.Add(tmpImgPath);
}
}
MessagingCenter.Send<App, List<string>>((App)Xamarin.Forms.Application.Current, "ImagesSelected", images);
}
}
}
And the GetActualPathFromFile (also in my MainActivity.cs)
The hole func is below but i hit this part of the code and get at "FileNotFound"
(...)
else if ("content".Equals(uri.Scheme, StringComparison.OrdinalIgnoreCase))
{
var retval2 = getDataColumn(this, uri, null, null);
if (File.Exists(retval2)) //<----------------------- This returns "false"
{
return retval2;
}
else
{
throw new Exception("file not found " + retval2);
}
}
(...)
The Hole GetActualPathFromFile
private string GetActualPathFromFile(Android.Net.Uri uri)
{
bool isKitKat = Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.Kitkat;
if (isKitKat && DocumentsContract.IsDocumentUri(this, uri))
{
// ExternalStorageProvider
if (isExternalStorageDocument(uri))
{
string docId = DocumentsContract.GetDocumentId(uri);
char[] chars = { ':' };
string[] split = docId.Split(chars);
string type = split[0];
if ("primary".Equals(type, StringComparison.OrdinalIgnoreCase))
{
var retval = Android.OS.Environment.ExternalStorageDirectory + "/" + split[1];
if (File.Exists(retval))
{
return retval;
}
else
{
throw new Exception("file not found " + retval);
}
}
}
// DownloadsProvider
else if (isDownloadsDocument(uri))
{
string id = DocumentsContract.GetDocumentId(uri);
Android.Net.Uri contentUri = ContentUris.WithAppendedId(
Android.Net.Uri.Parse("content://downloads/public_downloads"), long.Parse(id));
//System.Diagnostics.Debug.WriteLine(contentUri.ToString());
var retval = getDataColumn(this, contentUri, null, null);
if (File.Exists(retval))
{
return retval;
}
else
{
throw new Exception("file not found " + retval);
}
}
// MediaProvider
else if (isMediaDocument(uri))
{
String docId = DocumentsContract.GetDocumentId(uri);
char[] chars = { ':' };
String[] split = docId.Split(chars);
String type = split[0];
Android.Net.Uri contentUri = null;
if ("image".Equals(type))
{
contentUri = MediaStore.Images.Media.ExternalContentUri;
}
else if ("video".Equals(type))
{
contentUri = MediaStore.Video.Media.ExternalContentUri;
}
else if ("audio".Equals(type))
{
contentUri = MediaStore.Audio.Media.ExternalContentUri;
}
String selection = "_id=?";
String[] selectionArgs = new String[]
{
split[1]
};
var retval = getDataColumn(this, contentUri, selection, selectionArgs);
if (File.Exists(retval))
{
return retval;
}
else
{
throw new Exception("file not found " + retval);
}
}
}
// MediaStore (and general)
else if ("content".Equals(uri.Scheme, StringComparison.OrdinalIgnoreCase))
{
// Return the remote address
if (isGooglePhotosUri(uri))
{
var retval = uri.LastPathSegment;
if (File.Exists(retval))
{
return retval;
}
else
{
throw new Exception("file not found " + retval);
}
}
var retval2 = getDataColumn(this, uri, null, null);
if (File.Exists(retval2))
{
return retval2;
}
else
{
throw new Exception("file not found " + retval2);
}
}
// File
else if ("file".Equals(uri.Scheme, StringComparison.OrdinalIgnoreCase))
{
var retval = uri.Path;
if (File.Exists(retval))
{
return retval;
}
else
{
throw new Exception("file not found " + retval);
}
}
throw new Exception("file not found ");
}
public static String getDataColumn(Context context, Android.Net.Uri uri, String selection, String[] selectionArgs)
{
ICursor cursor = null;
String column = "_data";
String[] projection =
{
column
};
try
{
cursor = context.ContentResolver.Query(uri, projection, selection, selectionArgs, null);
if (cursor != null && cursor.MoveToFirst())
{
int index = cursor.GetColumnIndexOrThrow(column);
return cursor.GetString(index);
}
}
finally
{
if (cursor != null)
cursor.Close();
}
return null;
}
//Whether the Uri authority is ExternalStorageProvider.
public static bool isExternalStorageDocument(Android.Net.Uri uri)
{
return "com.android.externalstorage.documents".Equals(uri.Authority);
}
//Whether the Uri authority is DownloadsProvider.
public static bool isDownloadsDocument(Android.Net.Uri uri)
{
return "com.android.providers.downloads.documents".Equals(uri.Authority);
}
//Whether the Uri authority is MediaProvider.
public static bool isMediaDocument(Android.Net.Uri uri)
{
return "com.android.providers.media.documents".Equals(uri.Authority);
}
//Whether the Uri authority is Google Photos.
public static bool isGooglePhotosUri(Android.Net.Uri uri)
{
return "com.google.android.apps.photos.content".Equals(uri.Authority);
}
Found out that the real problem was that Google Photos App was not updating and was still showing images that were deleted.
After 2x reboot of the phone, Google Photos app finally updated.
So this looks more like a cache problem with Google Foto than a xamarin problem.

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

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

Anonymous types in LINQ

I am using the following code to get a record from my database table tblDatabases. I then populate Controls on a Form based on the value. I have used some functions to get the values needed for displaying in a text box (e.g. the display value is different than the value.
The DetailData is an object in my base form class. Initially I just got the record from the table as is and I was able to cast the DetailData to the tblDatabases and use reflection to get all of the values for the data and populate the controls on my form.
I am no longer able to cast the DetailData to my table because of the anonymous types.
I would like to be able to use reflection on the DetailData to get the values.
Thanks,
Brad
DetailData = (from db in priorityDataContext.tblDatabases
where db.DatabaseID == Id
select new
{
db.DatabaseID,
db.DatabaseName,
db.Purpose,
db.BackEnd,
db.FrontEnd,
db.Version,
db.ProducesReports,
db.MultiUser,
db.UserDescription,
Developer = priorityDataContext.func_get_employee_name(db.Developer),
DeptOwner = priorityDataContext.func_get_dept_name(db.DeptOwner),
db.Source_Code_Path,
db.Notes,
db.Active,
db.row_entry_time_stamp,
row_oper_name = priorityDataContext.func_get_employee_name(db.Developer),
db.row_last_chng_time_stamp,
row_last_chng_oper_name = priorityDataContext.func_get_employee_name(db.Developer)
}).SingleOrDefault();
protected virtual void PopulateDetailControlsA(List<Control> controlContainers, string srcDataTableName)
{
switch (srcDataTableName)
{
case "tblDatabase" :
break;
}
var database = (tblDatabase) DetailData;
var type = typeof(tblDatabase);
var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var controlContainer in controlContainers)
{
foreach (var propertyInfo in properties)
{
if (!ControlExists(controlContainer, propertyInfo.Name)) continue;
var txtExtControl = controlContainer.Controls[propertyInfo.Name] as ExtendedTextBox;
if (txtExtControl != null)
{
try
{
var value = propertyInfo.GetValue(database, null).ToString();
txtExtControl.Text = value;
}
catch (NullReferenceException)
{
}
continue;
}
var lnklblControl = controlContainer.Controls[propertyInfo.Name] as ExtendedLinkLabel;
if (lnklblControl != null)
{
try
{
var value = propertyInfo.GetValue(database, null).ToString();
lnklblControl.Text = value;
}
catch (NullReferenceException)
{
}
continue;
}
var chkControl = controlContainer.Controls[propertyInfo.Name] as ExtendedCheckBox;
if (chkControl != null)
{
try
{
var value = propertyInfo.GetValue(database, null).ToString();
switch (value)
{
case "True":
chkControl.CheckState = CheckState.Checked;
break;
case "False":
chkControl.CheckState = CheckState.Unchecked;
break;
}
}
catch (NullReferenceException)
{
chkControl.CheckState = CheckState.Indeterminate;
}
continue;
}
var cmbControl = controlContainer.Controls[propertyInfo.Name] as ExtendedComboBox;
if (cmbControl != null)
{
try
{
var value = propertyInfo.GetValue(database, null).ToString();
cmbControl.ValueMember = value;
}
catch (Exception ex)
{
}
continue;
}
}
}
}
What technology are you using for your UI? If you could use binding you would not need to worry about reflection on the anonymous type and then could also use converters if you need to format/calculate values from this.
From your response can't you just use the connection to the linq and then bind this to the combo box?
private void Form1_Load(object sender, System.EventArgs e)
{
var item = new DataClassesDataContext();
var stuff = item.Entity.Where(c => c.Property.Contains("something"));
comboBox1.DataSource = stuff;
comboBox1.DisplayMember = "Name";
comboBox1.ValueMember = "PIN";
}

Resources