Conversion directly in LINQ query - linq

I work with the Entity Framework and I have a LINQ query like this:
var foo = from ee in context.Table select new {id = ee.id, price = ee.price}.ToList();
where price is decimal (smallmoney in SqlServer).
Now I bind it to a datagridview by
mydgv.DataSource = foo;
But first, I would like to convert all the decimals to strings in order to remove zeros from the value (ex. now it is 26.0000 and I want it to be 26.00). How can I do that?
Something like:
bla.ForEach( x => x.price.ToString().Substring(0,3))
won't work.

var q = foo.Select(x => new { id = x.id, price = x.price.ToString("N2") } );
But you can probably set a format-string on the column in the datagridview to "N2" and bind directly to your original datasource. Something like:
dgv.Columns[0].DefaultCellStyle.Format = "N2";

Not sure if EF supports it, but try
new { ee.id, price = ee.price.ToString("f2") }

Related

Bind Objects To DataGridview and Reorder Column

I want to bind the object list to dataGridView.
Now i want the desired column to be the way i definde them. i.e., I want the objects to be order the way i want.
Like
var dataSource = linkItemListCommon.Select(x => new DataToBind { Select = x.Default, FileName = x.Text, CurrentDate = x.Date+" "+x.Time , PreviousDate = string.Empty, Size = x.Size }).ToList();
var filenamesList = new BindingList<DataToBind>(dataSource);
dgvDownLoadMaster.DataSource = filenamesList;
I want the datagrid columns to be in the order that i define.
Like here i expect them to be in order given below:
Select FileName CurrentDate PreviousDate Size
But the column list is appearing not as per my requirements.
How to Do that.Please help.
Create columns by hand and then you can order them easily. You can add columns trough designer and just set each column DataPropertyName to corresponding field.
Or you can create each column programmatically:
var col = new DataGridViewTextBoxColumn();
col.DataPropertyName = "Select ";
col.HeaderText = "Select";
col.Name = "ColSelect";
dgvDownLoadMaster.Columns.Add(col);
you have to do this for each column and do it before databinding.

how to use a dynamic variable in orderby clause

am a newbie in linq.. am stuck with one scenario. ie,
i have to sort the search results based on user input.
user inputs are Last Name, First Name and Title. for input 3 drop downs are there and i have to sort result based on the values selected.
i tried
order = Request["orders"].Split(',');
var param = order[0];
var p1 = typeof(Test).GetProperty(param);
param = order[1];
var p2 = typeof(Test).GetProperty(param);
param = order[2];
var p3 = typeof(Test).GetProperty(param);
model.Test = (from tests in model.Test
select tests).
OrderBy(x => p1.GetValue(x, null)).
ThenBy(x => p2.GetValue(x, null)).
ThenBy(x => p3.GetValue(x, null));
but it doesn't works.
i want qry like this
from tests in model.Test
select tests).OrderBy(x => x.lastname).
ThenBy(x => x.firstname).ThenBy(x => x.Title);
order[0]== lastname but how can i use it in the place of OrderBy(x => x.order[0])..?
Thanks in advance.
i solved my case as follows
// list of columns to be used for sorting
List<string>order = Request["orders"].Split(',').ToList();
//map the column string to property
var mapp = new Dictionary<string, Func<Test, string>>
{
{"FirstName", x => x.FirstName},
{"LastName", x => x.LastName},
{"SimpleTitle", x => x.SimpleTitle}
};
//user inputted order
var paras = new List<Func<Test, string>>();
foreach (var para in order)
{
if(!string.IsNullOrEmpty(para))
paras.Add(mapp[para]);
}
//sorting
model.Test= model.Test.OrderBy(paras[0]).ThenBy(paras[1]).ThenBy(paras[2]);
Thanks all,
Actually you are looking for dynamic linq query than you can try out Dynamic LINQ (Part 1: Using the LINQ Dynamic Query Library)
which allow to do like this
it means you can dynamically pass string propertyname to short you collection in orderby function
You can also read about : Dynamic query with Linq
You can compose the expression (any Expression) manually from pieces and then append it to the previous part of query. You can find more info, with example in "Sorting in IQueryable using string as column name".

LINQ create multiple new entities using a single ID field

I have a newbie LINQ question. I need to create two objects of same type from a list of strings. I need to append a text 'Direct' & "Indirect' to the string and use them as ID to create the two unique objects.
var vStrings = new List { "Milk", "Eggs", "Cheese" };
var vProducts = (from s in vStrings
select new Product { ID = s + "-Direct" })
.Union(
from s in vStrings
select new Product { ID = s + "-InDirect" });
You can see in the example above, I am using a Union to create two different objects, Is there a better way to rewrite this LINQ query?
Thanks for your suggestions
If you ever needed more suffixes, this might be a better way:
var strings = new List<string> { "Milk", "Eggs", "Cheese" };
var suffixes = new List<string> {"-Direct", "-InDirect"};
var products = strings
.SelectMany(_ => suffixes, (x, y) => new Product() {ID = x + y});
And it would only iterate over the original set of strings once.
This way isn't much shorter but I think it would be a little better such as there is only one Concat instead of many Union:
var vProducts2 = (from s in vStrings
select s + "-Direct").Concat(
from s in vStrings
select s + "-InDirect");

Linq - How to query specific columns and return a lists

I am trying to write a linq query that will only return certain columns from my entity object into a list object.
Below is my code which produces an error(can't implicitly convert a generic list of anonymous types to a generic list of type TBLPROMOTION):
IQueryable<TBLPROMOTION> matches = webStoreContext.TBLPROMOTION.Include("TBLSTORE").Include("LKPROMOTIONTYPE");
List<TBLPROMOTION> promotionInfo = null;
promotionInfo = (from p in matches
orderby p.PROMOTION_NM descending
select new { p.EFFECTIVE_DT, p.EXPIRE_DT, p.IS_ACTIVE,
p.PROMOTION_DESC, p.PROMOTION_ID, p.PROMOTION_NM }).ToList();
What would be the best way to accomplish this. I do not want to do a "select p" in this case and return all the columns associated with the query.
thanks in advance,
Billy
Can't you do var promotionInfo = () and get a list of anonymous types?
Okay, basically you can not cast an Anonymous type to a known type like TBLPROMOTION.
ofcourse, you can say var promotionInfo = and then get an IEnumerable<{Anonymoustype}> and use that to do, what you were wanting to do with promotionInfo.
Also, personally I prefer the Fluent version of a linq query, easy on the eyes, good programming diet, at least for me :)
var promotionInfo = matches
.OrderByDescending( p => p.PROMOTION_NM)
.Select( p => new { p.EFFECTIVE_DT,
p.EXPIRE_DT,
p.IS_ACTIVE,
p.PROMOTION_DESC,
p.PROMOTION_ID,
p.PROMOTION_NM})
.ToList();
If you're moving from a L2E query to a Type already defined, you may need a step between. I haven't tried to compile this but something like:
List<TBLPROMOTION> promotions = new List<TBLPROMOTION>();
var results = from p in matches
orderby p.PROMOTION_NM descending
select new
{
p.EFFECTIVE_DT,
p.EXPIRE_DT,
p.IS_ACTIVE,
p.PROMOTION_DESC,
p.PROMOTION_ID,
p.PROMOTION_NM
};
foreach (var v in results)
{
promotions.Add(new TBLPROMOTION(v.EFFECTIVE_DT, v.EXPIRE_DT, v.IS_ACTIVE,
v.PROMOTION_DESC, v.PROMOTION_ID, v.PROMOTION_NM));
}
Based on the comment below, you might try something like:
foreach(var v in results)
{
TBLPROMOTION temp = new TBLPROMOTION();
temp.EFFECTIVE_DT = v.EFFECTIVE_DT;
temp.EXPIRE_DT = v.EXPIRE_DT;
temp.IS_ACTIVE = v.IS_ACTIVE
// Assign Other Properties
promotions.Add(temp);
}
.......
Sorry: Just read the addition to the top.
Are you sure that none of the fields you're leaving out (instead of saying "select p") are required for a TBLPROMOTION object? Also, sense your TBLPROMOTION object is going to have properties (and therefore memory allocated) for those skipped fields, why not just use an annonymous type or set up a helper class that contains only your needed properties?
#Billy, following code worked for me.
List<TBLPROMOTION> promotionInfo =
(from p in matches
orderby p.PROMOTION_NM descending
select new TBLPROMOTION(p.EFFECTIVE_DT, p.EXPIRE_DT, p.IS_ACTIVE,
p.PROMOTION_DESC, p.PROMOTION_ID, p.PROMOTION_NM)
).ToList();
did you try
select new TBLPROMOTION {.....
instead of
select new {.....
List<TBLPROMOTION> promotionInfo = null;
promotionInfo = (from p in matches
orderby p.PROMOTION_NM descending
select new TBLPROMOTION { COL1 = p.EFFECTIVE_DT, COL2 = p.EXPIRE_DT, COL3 = p.IS_ACTIVE... }).ToList();
Where COL1, COL2, ... are the names of the properties on TBLPROMOTION you wish you populate.
If you want a subset of the table you have 2 options:
#Fredou mentioned select new TBLPROMOTION{...}
other way is to create a custom DTO which has the exact properties & select them instead like:
List promotionInfo = ...
select new TBLPROMOTION_DTO{
Effective_dt = ...
}
HTH

Building Dynamic LINQ Queries based on Combobox Value

I have a combo box in Silverlight. It has a collection of values built out of the properties of one of my LINQ-to-SQL objects (ie Name, Address, Age, etc...). I would like to filter my results based off the value selected in a combo box.
Example: Say I want everyone with a last name "Smith". I'd select 'Last Name' from the drop down list and enter smith into a textbox control. Normally I would write a LINQ query similar to...
var query = from p in collection where p.LastName == textbox.Text select p;
Is it possible to decide the property dynamically, maybe using Reflection? Something like
var query = from p in collection where p.(DropDownValue) == textbox.Text select p;
Assuming:
public class Person
{
public string LastName { get; set; }
}
IQueryable<Person> collection;
your query:
var query =
from p in collection
where p.LastName == textBox.Text
select p;
means the same as:
var query = collection.Where(p => p.LastName == textBox.Text);
which the compiler translates from an extension method to:
var query = Queryable.Where(collection, p => p.LastName == textBox.Text);
The second parameter of Queryable.Where is an Expression<Func<Person, bool>>. The compiler understands the Expression<> type and generates code to build an expression tree representing the lambda:
using System.Linq.Expressions;
var query = Queryable.Where(
collection,
Expression.Lambda<Func<Person, bool>>(
Expression.Equal(
Expression.MakeMemberAccess(
Expression.Parameter(typeof(Person), "p"),
typeof(Person).GetProperty("LastName")),
Expression.MakeMemberAccess(
Expression.Constant(textBox),
typeof(TextBox).GetProperty("Text"))),
Expression.Parameter(typeof(Person), "p"));
That is what the query syntax means.
You are free to call these methods yourself. To change the compared property, replace this:
typeof(Person).GetProperty("LastName")
with:
typeof(Person).GetProperty(dropDown.SelectedValue);
Scott Guthrie has a short series on dyamically built LINQ to SQL queries:
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
That's the easy way...then there's another way that's a bit more involved:
http://www.albahari.com/nutshell/predicatebuilder.aspx
You can also use the library I created: http://tomasp.net/blog/dynamic-linq-queries.aspx. You would store the properties in ComboBox as lambda expressions and then just write:
var f = (Expression<Func<Product, string>>)comboBox.SelectedValue;
var query =
from p in collection
where f.Expand(textBox.Text)
select p;

Resources