how to use an expression in a select clause - c#

consider the following pseudp code
Expression<Func<E,Datetime?>> expr =
e => (e.d1 ?? e.Rel.d1) ?? e.d2;
var q = myContext.E_DbSet.Select(x => new someDeclaredType {
Id = x.Id,
V = expr
});
=> CS0029 Cannot implicitly convert type 'System.Linq.Expressions.Expression>' to 'System.DateTime?'
if I try with compile
Expression<Func<E,Datetime?>> expr =
(e => (e.d1 ?? e.Rel.d1) ?? e.d2).Compile();
var q = myContext.E_DbSet.Select(x => new someDeclaredType {
Id = x.Id,
V = expr(x)
});
=> NotSupportedException: node type 'Invoke' of LINQ expression is not suported in LINQ to Entities.
I read Invoke an Expression in a Select statement - LINQ to Entity Framework. But this is not my exact case. I need to include an existing expression into my select clause. This expression comes as the result of a function call. So I must use expr in my select clause.
How can it be done ?

Maybe something like this:
Expression<Func<E,someDeclaredType>> expr =
e => new someDeclaredType()
{
Id = e.Id,
V = (e.d1 ?? e.Rel.d1) ?? e.d2
};
var q = myContext.E_DbSet.Select(expr);

I finally found a way:
Expression<Func<E,Datetime?>> expr =
e => (e.d1 ?? e.Rel.d1) ?? e.d2;
Expression<Func<E,someDeclaredType>> sel =
x => new someDeclaredType {
Id = x.Id,
V = expr.Compile()(x)
};
var q = myContext.E_DbSet.Select(sel.Compile());
another coding is (from #Anthony):
Expression<Func<E, someDeclaredType>> sel =
e => new someDeclaredType()
{
Id = e.Id,
V = expr.Compile()(e)
};
q = Files.Select(sel.Compile());
by the sample: dotnetfiddle
Please not that the code is designed for linq to entities. It may fire exception in linq to object due to Rel = null.

Related

how to set fields dynamicly in GroupBy in EF

I have below query :
var result = _workOrders.GroupBy(row => row.Asset, (k, g) => new AverageBetweenTwoFailureViewModel
{
// fields
}).ToList();
and know I need to set field dynamicly in row => row.Asset dynamicly .
I searched on the Net and I found below codes :
var arg = Expression.Parameter(typeof(Item), "item");
var body = Expression.Property(arg, "D");
var lambda = Expression.Lambda<Func<Item, DateTime>>(body, arg);
var keySelector = lambda.Compile();
but that override that I used in Groupby it's different.

Converting the Linq to Entity from query syntax to method syntax?

I have this LINQ to Entity:
var de = from dm in _context.DamageEvents
where dm.StatusID == statusId
group dm by new { dm.ClientId, dm.Client.ClientName, dm.SiteId, dm.Site.Name, dm.SiteObjectId } into g
select new
{
g.Key.ClientId,
g.Key.ClientName,
g.Key.SiteId,
g.Key.Name,
g.Key.SiteObjectId,
icon = g.Select(i=>i.SiteObject.ObjectModel.ObjectType.Icon).FirstOrDefault()
};
How can I convert the linq above to from query syntax to method syntax.
Any idea how can I implement it?
something like this?
var de = _context.DamageEvents.Where(dm => dm.StatusID == statusId)
.GroupBy(dm => new {dm.ClientId, dm.Client.ClientName, dm.SiteId, dm.Site.Name, dm.SiteObjectId})
.Select(g => new
{
g.Key.ClientId,
g.Key.ClientName,
g.Key.SiteId,
g.Key.Name,
g.Key.SiteObjectId,
icon = g.Select(i => i.SiteObject.ObjectModel.ObjectType.Icon).FirstOrDefault()
});

If Else in linq with anonymous object

How to do an If Else conditional in a LINQ query?
cashierdata.useDenominations is boolean type, i'm doing the casting to the same object .
Something like
IQueryable<CashierBalance> icashierBalance = _cashierDataManagement.GetIQueryableCashierBalance();
var currencies = icashierBalance.Select(a => new
{
Id = a.Currency.Id,
Name = a.Currency.Name,
Simbol = a.Currency.Symbol,
ShorName = a.Currency.ShortName,
RoundingUp = a.Currency.RoundingUp,
RoundingDown = a.Currency.RoundingDown,
DenominationMin = a.Currency.DenominationMin,
Denominations = cashierdata.useDenominations ? (Denomination) a.Currency.Denominations.Select(q => q )
: (Denomination) null
});
The response from the api
Unable to cast the type 'System.Collections.Generic.IEnumerable`1[[Tellers.Denomination, DynamicFieldsDiagramLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' to type 'Tellers.Denomination'. LINQ to Entities only supports casting EDM primitive or enumeration types.
Without casting
IQueryable<CashierBalance> icashierBalance = _cashierDataManagement.GetIQueryableCashierBalance();
var currencies = icashierBalance.Select(a => new
{
Id = a.Currency.Id,
Name = a.Currency.Name,
Simbol = a.Currency.Symbol,
ShorName = a.Currency.ShortName,
RoundingUp = a.Currency.RoundingUp,
RoundingDown = a.Currency.RoundingDown,
DenominationMin = a.Currency.DenominationMin,
Denominations = cashierdata.useDenominations ? a.Currency.Denominations.Select(q => q )
: null
});
the exception
The nested query is not supported. Operation1='Case' Operation2='Collect'
The problem is that your IQueryable is attempting to parse your expression and convert it into an SQL expression. This is beyond the capabilities of Entity Framework (specifically, it is unable to assign an enumerable of objects to Denominations).
In this case, you just want to fetch the data from the database, then perform your conversion in the .NET client.
To achieve this, convert your IQueryable to LINQ2Objects by invoking AsEnumerable.
IQueryable<CashierBalance> icashierBalance = _cashierDataManagement.GetIQueryableCashierBalance();
var currencies = icashierBalance
.AsEnumerable()
.Select(a => new
{
Id = a.Currency.Id,
Name = a.Currency.Name,
Simbol = a.Currency.Symbol,
ShorName = a.Currency.ShortName,
RoundingUp = a.Currency.RoundingUp,
RoundingDown = a.Currency.RoundingDown,
DenominationMin = a.Currency.DenominationMin,
Denominations = cashierdata.useDenominations ? a.Currency.Denominations.Select(q => q ) : null
});
Try this:
IQueryable<CashierBalance> icashierBalance = _cashierDataManagement.GetIQueryableCashierBalance();
var currencies = icashierBalance.Select(a => new
{
Id = a.Currency.Id,
Name = a.Currency.Name,
Simbol = a.Currency.Symbol,
ShorName = a.Currency.ShortName,
RoundingUp = a.Currency.RoundingUp,
RoundingDown = a.Currency.RoundingDown,
DenominationMin = a.Currency.DenominationMin,
Denominations = cashierdata.useDenominations ? a.Currency.Denominations : null
});

Expression.Lambda and query generation at runtime, simplest "Where" example

I was trying to generate a simple Lambda Expression at runtime with no luck... something like this:
var result = queryableData.Where(item => item.Name == "Soap")
Here is my example class and a fixture queryable:
public class Item
{
public int Id { get; set; }
public string Name { get; set; }
}
IQueryable<Item> queryableData = ...;
Then I generate a lambda expression at runtime correct code follows:
//"item" in "item =>..."
var item = Expression
.Parameter(typeof(Item), "item");
//property of my item, this is "item.Name"
var prop = Expression
.Property(item, "Name");
//then "Soap" in '... => item.Name=="Soap"'
var value = Expression.Constant("Soap");
//equality expression "==" in my primer
var equals = Expression.Equal(prop, value);
//then lambda
var lambda = Expression.Lambda<Func<Item, bool>>(equals, item);
//and here are the results
var results = queryableData.Where(lambda);
Big thanks to dtb for advice!
In the following query
var result = query.Where(item => item.Name == "Soap")
the lambda expression is
item => item.Name == "Soap"
You only need to construct this part, not the Where call which accepts an expression tree.
The expression tree for the lambda expression looks like this:
Lambda
/ \
Equal Parameter
/ \ item
Property \
"Name" Constant
| "Soap"
Parameter
item
In code:
var item = Expression.Parameter(typeof(Item), "item");
var prop = Expression.Property(item, "Name");
var soap = Expression.Constant("Soap");
var equal = Expression.Equal(prop, soap);
var lambda = Expression.Lambda<Func<Item, bool>>(equal, item);
var result = queryableData.Where(lambda);

How do you do alias in Select method (LINQ)

I'm trying to alias the string list with a named column:
var providers = EMRRepository.GetProviders().Select(x => x as name);
where 'GetProviders()' returns a List<string>
It's called a "Projection", just select a new anonymous type.
var projection = data.Select( x => new { FieldName = x.Property } );
You are looking to select into a new anonymous type.
var providers = EMRRepository.GetProviders().Select(x => new { Name = x });

Categories

Resources