LINQ What does 'select new' do? - c#

I've built the following LINQ query
var activeMembers = from m in context.py3_membershipSet
join c in context.ContactSet on m.py3_Member.Id equals c.ContactId
where m.statuscode.Value == 1
orderby m.py3_name
select m;
But I've since seen an example formatted as such:
var contacts =
(
from c in xrm.ContactSet
join a in xrm.AccountSet on c.ParentCustomerId.Id equals a.Id
where a.Name == "Acme Pty Ltd"
select new
{
Name = c.FullName,
DOB = c.BirthDate,
Gender = (c.FormattedValues.Contains("gendercode") ? c.FormattedValues["gendercode"] : "Ambiguous")
}
);
(I realise this is a different set of data) What does the inclusion of the 'select new' actually do in this case?
What are the benefits of it over my example in the first code block?
I realise some might find this a tedious question, but I a want to learn LINQ and need to learn it fast. But I also don't want to run something -that I don't fully understand- on a clients live CRM

LINQ returns a collection of anonymous objects, either way. select new let's you define the layout of that object and which properties/property names are included in that anonymous object.
You can also use select new ClassName { } to return a list of instances of an entity class that you define.

As previous answers have noted both methods return an anonymous type. To fully answer your question though: "What are the benefits of the second statement over the first?"
The first statement returns all of the fields of m as-is. If you have 7 "columns" then activeMembers will contain all of them and whatever data they contain.
In the second statement you're projecting the results into a custom anonymous object that has only 3 fields. Not only that but you can perform logic on the "source fields" before storing them in the anonymous object. This gives you much of the flexibility of storing them in a container class without you actually having to define that class in code.
You could also do select new SomeClass { } which would project your results into a predefined class container.
The following pseudo-code may or may not be helpful in understanding the difference:
var myQuery = from p in someContext.someTable
group p by p.someField into g
select new MyContainer {
Field1 = g.Sum(a => a.field1)
Field2 = g.Max(a => a.field2)
};
myQuery in the above is now a collection of MyContainer. If I had omitted the class MyContainer then it would be a collection of an Anonymous Type containing the fields that I specified. Obviously, the difference here is that MyContainer has to be defined elsewhere in your code whereas the anonymous class is built/defined for you at compile time. In:
var myQuery = from p in someContext.someTable
select p;
myQuery is an anonymous class containing all of the fields and their values in someTable.

You are using the Queryable.Select<TSource, TResult>(IQueryable<TSource>, Expression<Func<TSource, TResult>>) method where ContactSet is the TSource and the of anonymous object return type is the TResult. Your code could also be written as
...Select(r => new {
Name = c.FullName,
DOB = c.BirthDate,
Gender = (c.FormattedValues.Contains("gendercode") ? c.FormattedValues["gendercode"] : "Ambiguous")
})
where the select method is returning a collection of anonymous types.
Also, there is a bit more going on under the hood since it looks like you're querying the database. Your implementation of IQueryable looks at the Select method that you've written, and translates the expression you've provided into valid SQL so that it can retrieve all the necessary information for the anonymous object that you're returning. Notice that I said your implemenation of IQuerable translates the provided expression (not function) into sql. The Select extension method only accepts expressions, not functions because it can't translate functions to sql.

Related

Union Multiple Classes, Sort on Common Interface

This question is chiefly about LINQ and possibly covariance.
Two of my Entities implement the IDatedItem interface. I'd like to union, then sort these, for enumerating as a single list. I must retain entity-specific properties at enumeration-time.
To clarify by example, one approach I tried was:
Context.Table1.Cast<IDatedItem>().
Union(Context.Table2.Cast<IDatedItem>()).
SortBy(i => i.Date).
ForEach(u => CustomRenderSelector(u, u is Table1));
In trying to do this various ways, I've run into various errors.
LINQ to Entities only supports casting EDM primitive or enumeration types.
Unable to process the type '.IDatedItem[]', no known mapping to the value layer
Unable to create a constant value of type 'IDatedItem'. Only primitive types
etc.
The bigger picture:
The IDatedItem interface shown here is a simplification of the actual shared properties.
In practice, the tables are filtered before the union.
The entity-specific properties will be rendered, in order, in a web page.
In a parallel feature, they will be serialized to a JSON result hierarchy.
I'd like to be able to perform LINQ aggregate operations on the results as well.
This requires more space than a comment offers. On the other hand, this is not really an answer, because there is no satisfying answer, really.
For a Union to succeed, both collections must have the same type (or have intrinsic conversions to common types, that's what covariance is about).
So a first go at getting a correct Union could be:
Context.Table1.Select(t1 => new {
A = t1.PropA,
B = t1.PropB,
Date = t1.Date
})
.Union(
Context.Table1.Select(t2 => new {
A = t2.PropC,
B = t2.PropD,
Date = t2.Date
}))
.OrderBy(x => x.Date)
.ToList();
which projects both tables to the same anonymous type. Unfortunately, because of the anonymous type, you can't do .Cast<IDatedItem>().
Therefore, the only way to get a List<IDatedItem> is to define a type that implements IDatedItem and project both tables to that type:
Context.Table1.Select(t1 => new DateItem {
A = t1.PropA,
B = t1.PropB,
Date = t1.Date
})
.Union(
Context.Table1.Select(t2 => new DateItem {
A = t2.PropC,
B = t2.PropD,
Date = t2.Date
}))
.OrderBy(item => item.Date)
.AsEnumerable()
.Cast<IDatedItem>()
Which (I think) is quite elaborate. But as long as EF doesn't support casting to interfaces in linq queries it's the way to go.
By the way, contrary to what I said in my comment, the sorting will be done in SQL. And you can use subsequent aggregate functions on the result.
Here's the working code. My solution was to ensure all data was local, to keep LINQ-to-EF from trying to do all manner of things it knows it can't that were causing many unclear errors. Then a simple type declaration on the generic Union can take hold.
That means that, aside from the annoyances of LINQ-to-EF, the main issue here is really a duplicate of LINQ Union different types - dynamically casting to an interface? .
public virtual ActionResult Index() {
return View(StatusBoard().OrderBy(s => s.Status));
}
private IEnumerable<DefensiveSituationBoardMember> StatusBoard() {
DateTime now = DateTime.UtcNow;
DateTime historicalCutoff = now.AddDays(-1);
IEnumerable<Member> activeMembers = Context.Members.Where(n => !n.Disabled).ToList();
// IncomingAttack and Reinforcements both implement IDefensiveActivity
IEnumerable<IncomingAttack> harm = Context.IncomingAttacks.Where(n => n.IsOngoingThreat || n.ArrivalOn > historicalCutoff).ToList();
IEnumerable<Reinforcements> help = Context.Reinforcements.Where(n => !n.Returned.HasValue || n.Returned > historicalCutoff).ToList();
// Here's the relevant fix
IEnumerable<IDefensiveActivity> visibleActivity = help.Union<IDefensiveActivity>(harm);
return from member in activeMembers
join harmEntry in harm on member equals harmEntry.DestinationMember into harmGroup
join activityEntry in visibleActivity on member equals activityEntry.DestinationMember into activityGroup
select new DefensiveSituationBoardMember {
Member = member,
Posture = harmGroup.Max(i => (DefensivePostures?)i.Posture),
Activity = activityGroup.OrderBy(a => a.ArrivalOn)
};
}

Dynamic Linq - Joining a table with 1 to many relationship

I'm using Dynamic Linq as the backend to an in-app reporting tool and I've hit a problem that I can't get round where I have to access a table that has a 1:M relationship .
My simplified data structure is this:
If I were querying this in standard Linq I'd write the query as:
from a in context.Table_A
select new
{
a.RefNo,
val = from b in a.Table_B
where (b.A_ID == a.ID)
where (b.code == "A0001"
select(b.Value).FirstOrDefault()
}
This works without any problem. However, when I try the query using Dynamic Linq I can't get the join to work.
From the code below you can see what I'm getting at but obviously I can't use the "a." and the "a.Table_B" references in the query. What do I have to do to be able to access Table_B in this context?
string select = "new (Ref_No,
val = from b in a.Table_B
where (b.A_ID == a.ID)
where (b.code == \"A0001\"
select(b.Value).FirstOrDefault()";
var results = context.Table_A.Select(select);
Edit 1:
To answer #Hogan's comment - Why don't I use join: The reports system is dynamic and the select statement may or may not be joining on to Table_B (or indeed joining on to Table_B multiple times) so the join has to be optional. My other issue with this is that unlike the Select method where I can pass in a string as a parameter (allowing me to make it dynamic quite easily) the Join() method can't be called in that way. The closest thing I've found is a dynamic Linq join extention method, something I may have to consider using but I've a feeling that this will be cumbersome with the dynamic select().
Edit 2:
Based on Hogan's suggestions I've got this far:
delegate string searchTableA(Table_A a);
public void Search()
{
....
searchTableA sel = (a) =>
{
return (from b in context.Table_B
where (b.A_ID == a.ID)
select (b.Value)).FirstOrDefault();
};
var res = context.Table_A.Select(sel);
}
This gives the error: 'System.Data.Entity.DbSet<TestDynamicLinqJoins.Table_A>' does not contain a definition for 'Select' and the best extension method overload 'System.Linq.Dynamic.DynamicQueryable.Select(System.Linq.IQueryable, string, params object[])' has some invalid arguments
Hard to give exact code because I don't know the types of your elements, but something like this would work fine using delegates.
delegate string searchTableA(elementType a);
searchTableA sel = (a) =>
{
return from b in a.Table_B
where (b.A_ID == a.ID)
where (b.code == "A0001")
select(b.Value).FirstOrDefault();
};
var results = context.Table_A.Select(sel);

Is it possible to create anonymous type in LINQ extension methods in C#?

Is it possible to create anonymous type in LINQ extension methods in C#?
For example LINQ query.i.e.
var CAquery = from temp in CAtemp
join casect in CAdb.sectors
on temp.sector_code equals casect.sector_code
select new
{
//anonymous types
CUSIP = temp.equity_cusip,
CompName = temp.company_name,
Exchange = temp.primary_exchange
};
Is the same behavior supported for LINQ extension methods in C#?
Do you mean "when using the extension method syntax"? If so, absolutely. Your query is exactly equivalent to:
var CAquery = CAtemp.Join(CAdb.sectors,
temp => temp.sector_code,
casect => casect.sector_code,
(temp, casect) => new
{
CUSIP = temp.equity_cusip,
CompName = temp.company_name,
Exchange = temp.primary_exchange
});
The C# language specification sets out all the translations in section 7.16. Note that in this case, as your join clause was only followed by a select clause, the projection is performed within the Join call. Otherwise (e.g. if you had a where clause) the compiler would have introduced transparent identifiers to keep the two range variables (temp and casect) available, via a new anonymous type which just kept the pair of them in a single value.
Every query expression is expressible as non-query-expression code. Query expressions are effectively a form of preprocessing.
something like this maybe...
var CAquery=CATemp.Join(.....)
.Select(temp=>new
{
CUSIP = temp.equity_cusip,
CompName = temp.company_name,
Exchange = temp.primary_exchange
});
The LINQ query you have shown is an extension method. It will simply be transformed by the compiler into a call to the Join extension method. You can create an anonymous type anywhere you can create any type, which include inside any extension methods.

anonymous types, when is it useful?

How could this anonymous type be useful in real life situation? Why is it good to be anoynimous?
// sampleObject is an instance of a simple anonymous type.
var sampleObject =
new { FirstProperty = "A", SecondProperty = "B" };
From MSDN Anonymous Types (C# Programming Guide):
Anonymous types typically are used in the select clause of a query
expression to return a subset of the properties from each object in
the source sequence.
...
The most common scenario is to initialize an anonymous type with
properties from another type.
For extra info, you may read Anonymous Types in Query Expressions.
Also, consider reading SO What is the purpose of anonymous types?
Consider an example from How to: Join by Using Composite Keys (C# Programming Guide):
var query = from o in db.Orders
from p in db.Products
join d in db.OrderDetails
on new { o.OrderID, p.ProductID }
equals new { d.OrderID, d.ProductID }
into details
from d in details
select new { o.OrderID, p.ProductID, d.UnitPrice };
This example shows how to perform join operations in which you want to
use more than one key to define a match. This is accomplished by using
a composite key. You create a composite key as an anonymous type or
named typed with the values that you want to compare.
And an example of using anonymous types for grouping dara to encapsulate a key that contains multiple values from Group by Multiple Columns using Anonymous Types in LINQ to SQL:
var months = from t in db.TransactionData
group t by new { month = t.Date.Month, year = t.Date.Year }
into d
select new { t.Key.month, t.Key.year };
or beter How to: Group Query Results (C# Programming Guide):
An anonymous type is used because it is not necessary to use the
complete object to display the results
Note that the properties in the anonymous type become properties on
the Key member and can be accessed by name when the query is executed.
Typically, when you use an anonymous type to initialize a variable, you declare the variable as an implicitly typed local variable by using var. The type name cannot be specified in the variable declaration because only the compiler has access to the underlying name of the anonymous type. For more information about var, see Implicitly Typed Local Variables (C# Programming Guide).

Linq to Entities - Projections against Query Syntax vs Method Syntax

Since LINQ query expression are translated "under the covers" to call the same methods that a corresponding method query would call (at least I think so), I would expect these two queries to return the same type. For some reason though this:
var result = from i in db.Invoices
select new { i.InvoiceNum };
sets result as an IQueryable<'a> with each member having an InvoiceNum property, while this
IQueryable<string> result2 = db.Invoices.Select(i => i.InvoiceNum);
Is smart enough to return IQueryable<string> (obviously, since that compiles)
Clearly one of my assumptions is wrong, and I was hoping an expert could help me understand a bit better.
(this is EF4, but the same happens with linq-to-objects, and I'm guessing the same would also happen with L2S)
When you write new { } you are creating an anonymous type
try
var result = from i in db.Invoices
select i.InvoiceNum;
and you will see that it returns the type you expect.
those are not the same, the first one is returning anonymousn type, to make them the same you need to have th first one as:
var result = from i in db.Invoices
select i.InvoiceNum;
In your first statement, you create an anonymous type with one property named "InvoiceNum". This happens because you use the new { } syntax. That anonymous type is not a String. The equivalent method syntax would be:
var result = db.Invoices.Select(i => new { i.InvoiceNum });

Categories

Resources